Refactor import of radial grid

* Add radial display mode to preferences
* Adds isRadial to grid
* Improve mesh lines for radial cells
For temporary radial LGRs, show mesh outline based on the aggregated geometry of all LGRs of the parent cell clicked on.
* Improve warning message
* Modify cell selection in pick event handler
This commit is contained in:
Magne Sjaastad authored and GitHub committed 2025-09-29 11:46:28 +02:00
1 parent 4421536349
commit 6b7d93e2da
25 files changed
+399 -241

No files matched your search

@@ -38,6 +38,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaCloudDefines.h
${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.h
${CMAKE_CURRENT_LIST_DIR}/RiaQuickAccessScheduler.h
${CMAKE_CURRENT_LIST_DIR}/RiaGridDefines.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -80,6 +81,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaCloudDefines.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaWellFlowDefines.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaQuickAccessScheduler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaGridDefines.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
@@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 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 "RiaGridDefines.h"
#include "cafAppEnum.h"
namespace caf
{
template <>
void caf::AppEnum<RiaGridDefines::RadialGridMode>::setUp()
{
addItem( RiaGridDefines::RadialGridMode::CARTESIAN, "CARTESIAN", "Show Cells as Cartesian Hex Elements" );
addItem( RiaGridDefines::RadialGridMode::CYLINDRICAL, "CYLINDRICAL", "Show Cells as Cylinder Segments" );
setDefault( RiaGridDefines::RadialGridMode::CYLINDRICAL );
}
} // namespace caf
@@ -0,0 +1,30 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
namespace RiaGridDefines
{
enum class RadialGridMode
{
CYLINDRICAL,
CARTESIAN
};
};
@@ -97,6 +97,8 @@ RiaPreferencesGrid::RiaPreferencesGrid()
CAF_PDM_InitField( &m_invalidateLongThinCells, "invalidateLongThinCells", false, "Skip Long, Thin Cells" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_invalidateLongThinCells );
CAF_PDM_InitFieldNoDefault( &m_radialGridMode, "radialGridMode", "Radial Grid Display Mode" );
}
//--------------------------------------------------------------------------------------------------
@@ -146,6 +148,8 @@ void RiaPreferencesGrid::appendItems( caf::PdmUiOrdering& uiOrdering )
egridGrp->add( &m_useResultIndexFile );
}
egridGrp->add( &m_radialGridMode );
const bool setFaultImportSettingsReadOnly = !importFaults();
m_includeInactiveCellsInFaultGeometry.uiCapability()->setUiReadOnly( setFaultImportSettingsReadOnly );
@@ -176,7 +180,7 @@ RifReaderSettings RiaPreferencesGrid::readerSettings()
.includeFileAbsolutePathPrefix = m_includeFileAbsolutePathPrefix,
.onlyLoadActiveCells = m_onlyLoadActiveCells,
.invalidateLongThinCells = m_invalidateLongThinCells,
.useCylindricalCoordinates = RiaPreferencesSystem::current()->useCylindricalCoordinates(),
.useCylindricalCoordinates = m_radialGridMode == RiaGridDefines::RadialGridMode::CYLINDRICAL,
.minimumAngularCellCount = RiaPreferencesSystem::current()->minimumAngularCellCount()
};
@@ -327,3 +331,10 @@ RiaDefines::GridModelReader RiaPreferencesGrid::gridModelReaderOverride() const
{
return m_gridModelReaderOverride;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaGridDefines::RadialGridMode RiaPreferencesGrid::radialGridMode() const
{
return m_radialGridMode();
}
@@ -23,6 +23,7 @@
#include "cafPdmObject.h"
#include "RiaDefines.h"
#include "RiaGridDefines.h"
#include <QString>
@@ -63,6 +64,8 @@ public:
void setGridModelReaderOverride( const RiaDefines::GridModelReader readerType );
RiaDefines::GridModelReader gridModelReaderOverride() const;
RiaGridDefines::RadialGridMode radialGridMode() const;
void appendItems( caf::PdmUiOrdering& uiOrdering );
private:
@@ -80,4 +83,6 @@ private:
caf::PdmField<bool> m_loadAndShowSoil;
caf::PdmField<bool> m_onlyLoadActiveCells;
caf::PdmField<bool> m_invalidateLongThinCells;
caf::PdmField<caf::AppEnum<RiaGridDefines::RadialGridMode>> m_radialGridMode;
};
@@ -77,9 +77,6 @@ RiaPreferencesSystem::RiaPreferencesSystem()
CAF_PDM_InitField( &m_showPdfExportDialog, "showPdfExportDialog", true, "Show PDF Export Dialog" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_showPdfExportDialog );
CAF_PDM_InitField( &m_useCylindricalCoordinates, "useCylindricalCoordinates", true, "Use Cylindrical Coords" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_useCylindricalCoordinates );
CAF_PDM_InitField( &m_mimimumAngularCellCount, "mimimumAngularCellCount", 40, "Minimum Angular Cell Count" );
CAF_PDM_InitField( &m_gtestFilter, "gtestFilter", QString(), "Unit Test Filter (gtest)" );
@@ -244,14 +241,6 @@ std::optional<int> RiaPreferencesSystem::threadCount() const
return text.toInt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferencesSystem::useCylindricalCoordinates() const
{
return m_useCylindricalCoordinates();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -312,7 +301,6 @@ void RiaPreferencesSystem::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Radial Grid" );
group->add( &m_useCylindricalCoordinates );
group->add( &m_mimimumAngularCellCount );
}
@@ -59,8 +59,7 @@ public:
std::optional<int> threadCount() const;
bool useCylindricalCoordinates() const;
int minimumAngularCellCount() const;
int minimumAngularCellCount() const;
EclipseTextFileReaderMode eclipseTextFileReaderMode() const;
@@ -89,8 +88,7 @@ private:
caf::PdmField<bool> m_showProgressBar;
caf::PdmField<bool> m_useCylindricalCoordinates;
caf::PdmField<int> m_mimimumAngularCellCount;
caf::PdmField<int> m_mimimumAngularCellCount;
caf::PdmField<QString> m_gtestFilter;
@@ -81,6 +81,7 @@ bool RifOpmRadialGridTools::importCylindricalCoordinates( const std::string& gri
if ( opmMainGrid.is_radial() )
{
riMainGrid->setIsRadial( true );
transferCylindricalCoords( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
auto minimumAngularCellCount = RiaPreferencesSystem::current()->minimumAngularCellCount();
@@ -112,7 +113,7 @@ bool RifOpmRadialGridTools::importCylindricalCoordinates( const std::string& gri
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
bool RifOpmRadialGridTools::tryConvertRadialGridToCartesianGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
{
try
{
@@ -146,7 +147,7 @@ bool RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& g
if ( opmMainGrid.is_radial() )
{
transferCoordinatesRadial( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
convertRadialGridToCartesianGrid( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
}
auto lgrNames = opmMainGrid.list_of_lgrs();
@@ -161,7 +162,7 @@ bool RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& g
auto riLgrGrid = riMainGrid->gridByIndex( i );
if ( riLgrGrid->gridName() == lgrName )
{
transferCoordinatesRadial( opmMainGrid, opmLgrGrid, riMainGrid, riLgrGrid );
convertRadialGridToCartesianGrid( opmMainGrid, opmLgrGrid, riMainGrid, riLgrGrid );
}
}
}
@@ -252,10 +253,10 @@ void RifOpmRadialGridTools::transferCylindricalCoords( Opm::EclIO::EGrid& opmMai
// 2. Find the closest point on the pillars of the host cell
// 3. Find the closest point on this pillar, and use this point as the adjusted coordinate for the node
//--------------------------------------------------------------------------------------------------
void RifOpmRadialGridTools::transferCoordinatesRadial( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid )
void RifOpmRadialGridTools::convertRadialGridToCartesianGrid( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid )
{
size_t cellCount = opmGrid.totalNumberOfCells();
if ( cellCount != riGrid->cellCount() ) return;
@@ -417,7 +418,8 @@ bool RifOpmRadialGridTools::createAngularGridRefinement( RigEclipseCaseData* cas
LgrInfo lgrInfo{ id, "Radial LGR", "", refinement, mainGridStart, mainGridEnd };
RicCreateTemporaryLgrFeature::createLgr( lgrInfo, caseData );
auto grid = RicCreateTemporaryLgrFeature::createLgr( lgrInfo, caseData );
grid->setIsRadial( true );
// Convert the radial grid to a Cartesian grid
std::vector<cvf::Vec3d>& nodes = riMainGrid->nodes();
@@ -43,7 +43,7 @@ class RifOpmRadialGridTools
{
public:
// If the grid is radial, the coordinates are imported and adjusted to fit the host cells
static bool importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
static bool tryConvertRadialGridToCartesianGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
static bool importCylindricalCoordinates( const std::string& gridFilePath, RigEclipseCaseData* caseData );
@@ -67,8 +67,10 @@ private:
static void
transferCylindricalCoords( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid );
static void
transferCoordinatesRadial( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid );
static void convertRadialGridToCartesianGrid( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid );
static std::vector<std::vector<cvf::Vec3d>>
computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex );
@@ -23,8 +23,8 @@
#include "RiaCellDividingTools.h"
#include "RiaEclipseUnitTools.h"
#include "RiaLogging.h"
#include "RiaStringEncodingTools.h"
#include "RifActiveCellsReader.h"
#include "RifEclipseInputFileTools.h"
#include "RifEclipseOutputFileTools.h"
@@ -428,30 +428,50 @@ bool RifReaderEclipseOutput::open( const QString& fileName, RigEclipseCaseData*
buildMetaData( mainEclGrid );
}
if ( readerSettings().useCylindricalCoordinates )
{
// Check if min J coordinate is close to 0.0 and max is close to 360. This is a workaround for import of simulation cases that
// has an invalid header and is not possible to import using opm-common
RigMainGrid* mainGrid = eclipseCaseData->mainGrid();
if ( !mainGrid->boundingBox().isValid() )
auto isAngularRangeCylindrical = [&]()
{
mainGrid->computeBoundingBox();
}
auto bb = mainGrid->boundingBox();
const double epsilon = 1.0;
if ( bb.isValid() && ( std::abs( bb.min().y() ) < epsilon ) && ( std::abs( bb.max().y() - 360.0 ) < epsilon ) )
{
m_isRadialGrid = true;
size_t minimumAngularCellCount = static_cast<size_t>( readerSettings().minimumAngularCellCount );
if ( mainGrid->cellCountJ() < minimumAngularCellCount )
// Check if min J coordinate is close to 0.0 and max is close to 360. This is a workaround for import of simulation cases that
// has an invalid header and is not possible to import using opm-common
if ( !mainGrid->boundingBox().isValid() )
{
auto angularRefinement = ( minimumAngularCellCount / mainGrid->cellCountJ() ) + 1;
RifOpmRadialGridTools::createAngularGridRefinement( eclipseCaseData, angularRefinement );
mainGrid->computeBoundingBox();
}
auto bb = mainGrid->boundingBox();
const double epsilon = 1.0;
return ( bb.isValid() && ( std::abs( bb.min().y() ) < epsilon ) && ( std::abs( bb.max().y() - 360.0 ) < epsilon ) );
};
bool isDetectedAsRadial = isAngularRangeCylindrical();
if ( isDetectedAsRadial )
{
if ( !readerSettings().useCylindricalCoordinates )
{
QString msg = QString( "The grid appears to be a radial grid. To import this grid, open Preferences, and set Radial "
"import mode to 'Show Cells as Cylinder Segments'." );
RiaLogging::errorInMessageBox( nullptr, "Potential Radial Grid", msg );
}
if ( readerSettings().useCylindricalCoordinates )
{
mainGrid->setIsRadial( true );
size_t minimumAngularCellCount = static_cast<size_t>( readerSettings().minimumAngularCellCount );
if ( mainGrid->cellCountJ() < minimumAngularCellCount )
{
auto angularRefinement = ( minimumAngularCellCount / mainGrid->cellCountJ() ) + 1;
RifOpmRadialGridTools::createAngularGridRefinement( eclipseCaseData, angularRefinement );
}
}
}
else
{
auto isRadial = RifOpmRadialGridTools::tryConvertRadialGridToCartesianGrid( fileName.toStdString(), eclipseCaseData->mainGrid() );
mainGrid->setIsRadial( isRadial );
}
}
@@ -1148,14 +1168,6 @@ void RifReaderEclipseOutput::updateFromGridCount( size_t gridCount )
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderEclipseOutput::isRadialGrid() const
{
return m_isRadialGrid;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -88,8 +88,6 @@ public:
void updateFromGridCount( size_t gridCount ) override;
bool isRadialGrid() const override;
private:
bool readActiveCellInfo();
@@ -126,5 +124,4 @@ private:
mutable cvf::ref<RifEclipseRestartDataAccess> m_dynamicResultsAccess; // File access to dynamic results
std::unique_ptr<RifHdf5ReaderInterface> m_hdfReaderInterface;
bool m_isRadialGrid = false;
};
@@ -113,14 +113,6 @@ std::set<RiaDefines::PhaseType> RifReaderInterface::availablePhases() const
return std::set<RiaDefines::PhaseType>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderInterface::isRadialGrid() const
{
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -79,8 +79,6 @@ public:
virtual void updateFromGridCount( size_t gridCount ) {};
virtual bool isRadialGrid() const;
protected:
bool isTimeStepIncludedByFilter( size_t timeStepIndex ) const;
size_t timeStepIndexOnFile( size_t timeStepIndex ) const;
@@ -118,13 +118,20 @@ bool RifReaderOpmCommon::open( const QString& fileName, RigEclipseCaseData* ecli
buildMetaData( eclipseCaseData, progress );
}
if ( readerSettings().useCylindricalCoordinates && m_radialGridDetected )
if ( m_radialGridDetected )
{
auto task = progress.task( "Check for Radial Grid", 25 );
bool isLgrCreated = RifOpmRadialGridTools::importCylindricalCoordinates( fileName.toStdString(), m_eclipseCaseData );
if ( isLgrCreated )
if ( readerSettings().useCylindricalCoordinates )
{
m_eclipseCaseData->clearWellCellsInGridCache();
auto task = progress.task( "Check for Radial Grid", 25 );
bool isLgrCreated = RifOpmRadialGridTools::importCylindricalCoordinates( fileName.toStdString(), m_eclipseCaseData );
if ( isLgrCreated )
{
m_eclipseCaseData->clearWellCellsInGridCache();
}
}
else
{
RifOpmRadialGridTools::tryConvertRadialGridToCartesianGrid( fileName.toStdString(), eclipseCaseData->mainGrid() );
}
}
@@ -152,8 +159,12 @@ bool RifReaderOpmCommon::open( const QString& fileName, RigEclipseCaseData* ecli
}
catch ( std::exception& e )
{
auto description = e.what();
RiaLogging::error( description );
RiaLogging::debug( e.what() );
QString errorMsg = "Unable to read cell data from grid. Change grid reader to resdata and try again.";
RiaLogging::error( errorMsg );
return false;
}
return true;
@@ -1060,14 +1071,6 @@ std::vector<QDateTime> RifReaderOpmCommon::timeStepsOnFile( QString gridFileName
return dateTimes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderOpmCommon::isRadialGrid() const
{
return m_radialGridDetected;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -61,8 +61,6 @@ public:
std::vector<QDateTime> timeStepsOnFile( QString gridFileName );
bool isRadialGrid() const override;
protected:
virtual bool importGrid( RigMainGrid* mainGrid, RigEclipseCaseData* caseData );
@@ -22,50 +22,31 @@
#include "RiaLogging.h"
#include "RiaPreferences.h"
#include "RiaPreferencesGrid.h"
#include "RiaRegressionTestRunner.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigResultAccessorFactory.h"
#include "RimCellEdgeColors.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseView.h"
#include "RimRegularLegendConfig.h"
#include "RimReservoirCellResultsStorage.h"
#include "RimSimWellInViewCollection.h"
#include "RimTernaryLegendConfig.h"
#include "RivCellEdgeEffectGenerator.h"
#include "RivCompletionTypeResultToTextureMapper.h"
#include "RivMeshLinesSourceInfo.h"
#include "RivPartPriority.h"
#include "RivResultToTextureMapper.h"
#include "RivScalarMapperUtils.h"
#include "RivSingleCellPartGenerator.h"
#include "RivSourceInfo.h"
#include "RivTernaryScalarMapperEffectGenerator.h"
#include "RivTernaryTextureCoordsCreator.h"
#include "RivTextureCoordsCreator.h"
#include "cafEffectGenerator.h"
#include "cafPdmFieldCvfColor.h"
#include "cafPdmFieldCvfMat4d.h"
#include "cafProgressInfo.h"
#include "cvfDrawableGeo.h"
#include "cvfModelBasicList.h"
#include "cvfPart.h"
#include "cvfRenderStateBlending.h"
#include "cvfRenderStatePolygonOffset.h"
#include "cvfRenderState_FF.h"
#include "cvfShaderProgram.h"
#include "cvfShaderProgramGenerator.h"
#include "cvfShaderSourceProvider.h"
#include "cvfShaderSourceRepository.h"
#include "cvfStructGrid.h"
#include "cvfTransform.h"
#include "cvfUniform.h"
namespace caf
{
@@ -196,7 +177,29 @@ void RivGridPartMgr::generatePartGeometry( cvf::StructGridGeometryGenerator& geo
// Mesh geometry
{
cvf::ref<cvf::DrawableGeo> geoMesh = geoBuilder.createMeshDrawable();
cvf::ref<cvf::DrawableGeo> geoMesh;
if ( RiaPreferencesGrid::current()->radialGridMode() == RiaGridDefines::RadialGridMode::CYLINDRICAL && m_grid->isRadial() &&
m_grid->isTempGrid() )
{
std::vector<size_t> localGridCellIndices;
for ( size_t i = 0; i < m_grid->cellCount(); i++ )
{
if ( ( *m_cellVisibility )[i] )
{
localGridCellIndices.push_back( i );
}
}
geoMesh = RivSingleCellPartGenerator::createMeshLinesOfParentGridCells( m_grid.p(),
localGridCellIndices,
m_eclipseCase->displayModelOffset() );
}
else
{
geoMesh = geoBuilder.createMeshDrawable();
}
if ( geoMesh.notNull() )
{
if ( useBufferObjects )
@@ -19,12 +19,16 @@
#include "RivSingleCellPartGenerator.h"
#include "RiaPreferencesGrid.h"
#include "RigCell.h"
#include "RigEclipseCaseData.h"
#include "RigFemPartCollection.h"
#include "RigGeoMechCaseData.h"
#include "RigGridBase.h"
#include "RigReservoirGridTools.h"
#include "RimEclipseCase.h"
#include "RimGeoMechCase.h"
#include "RivFemPartGeometryGenerator.h"
@@ -100,6 +104,114 @@ cvf::ref<cvf::Part> RivSingleCellPartGenerator::createPart( const cvf::Color3f c
return part;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<cvf::DrawableGeo> RivSingleCellPartGenerator::createMeshLinesOfParentGridCells( RigGridBase const* grid,
std::vector<size_t>& localGridCellIndices,
const cvf::Vec3d& displayModelOffset )
{
if ( !grid ) return nullptr;
// create a map with parent cell index as key and vector of local grid cell indices as value
std::map<size_t, std::vector<size_t>> parentCellToLocalGridCellsMap;
for ( auto cellIndex : localGridCellIndices )
{
const auto cell = grid->cell( cellIndex );
auto parentCellIndex = cell.parentCellIndex();
parentCellToLocalGridCellsMap[parentCellIndex].push_back( cellIndex );
}
std::vector<cvf::Vec3d> quadVertices;
std::vector<cvf::Vec3d> lineVertexPairs;
for ( const auto& [cellIndexInMainGrid, lgrCellIndices] : parentCellToLocalGridCellsMap )
{
for ( auto cellIndex : lgrCellIndices )
{
std::array<cvf::Vec3d, 8> cornerVerts = grid->cellCornerVertices( cellIndex );
cvf::ubyte faceConn[4];
// Show grid lines for vertical lines along the radius of the cylinder segment
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::NEG_I, faceConn );
lineVertexPairs.push_back( cornerVerts[faceConn[1]] );
lineVertexPairs.push_back( cornerVerts[faceConn[2]] );
lineVertexPairs.push_back( cornerVerts[faceConn[3]] );
lineVertexPairs.push_back( cornerVerts[faceConn[0]] );
// Show grid lines for vertical lines along the radius of the cylinder segment
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::POS_I, faceConn );
lineVertexPairs.push_back( cornerVerts[faceConn[0]] );
lineVertexPairs.push_back( cornerVerts[faceConn[1]] );
lineVertexPairs.push_back( cornerVerts[faceConn[2]] );
lineVertexPairs.push_back( cornerVerts[faceConn[3]] );
// Show quad lines for min/max J faces
if ( cellIndex == lgrCellIndices.back() )
{
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::POS_J, faceConn );
quadVertices.push_back( cornerVerts[faceConn[0]] );
quadVertices.push_back( cornerVerts[faceConn[1]] );
quadVertices.push_back( cornerVerts[faceConn[2]] );
quadVertices.push_back( cornerVerts[faceConn[3]] );
}
if ( cellIndex == lgrCellIndices.front() )
{
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::NEG_J, faceConn );
quadVertices.push_back( cornerVerts[faceConn[0]] );
quadVertices.push_back( cornerVerts[faceConn[1]] );
quadVertices.push_back( cornerVerts[faceConn[2]] );
quadVertices.push_back( cornerVerts[faceConn[3]] );
}
}
}
std::vector<cvf::Vec3f> displayVertices;
for ( const auto& v : quadVertices )
{
displayVertices.push_back( cvf::Vec3f( v - displayModelOffset ) );
}
cvf::ref<cvf::Vec3fArray> cvfVertices = new cvf::Vec3fArray;
cvfVertices->assign( displayVertices );
if ( !cvfVertices.notNull() || cvfVertices->size() == 0 ) return nullptr;
ref<UIntArray> indices = StructGridGeometryGenerator::lineIndicesFromQuadVertexArray( cvfVertices.p() );
// Add vertex pairs as lines
const auto quadVertexCount = cvfVertices->size();
const auto indicesCount = indices->size();
cvfVertices->resize( quadVertexCount + lineVertexPairs.size() );
indices->resize( indicesCount + lineVertexPairs.size() );
size_t iIndex = indicesCount;
size_t vIndex = quadVertexCount;
for ( const auto& v : lineVertexPairs )
{
indices->set( iIndex++, static_cast<cvf::uint>( vIndex ) );
cvfVertices->set( vIndex++, cvf::Vec3f( v - displayModelOffset ) );
}
ref<DrawableGeo> geo = new DrawableGeo;
geo->setVertexArray( cvfVertices.p() );
ref<PrimitiveSetIndexedUInt> prim = new PrimitiveSetIndexedUInt( PT_LINES );
prim->setIndices( indices.p() );
geo->addPrimitiveSet( prim.p() );
return geo;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -107,14 +219,17 @@ cvf::ref<cvf::DrawableGeo> RivSingleCellPartGenerator::createMeshDrawable()
{
if ( m_rigCaseData && m_cellIndex != cvf::UNDEFINED_SIZE_T )
{
if ( m_showLgrMeshLines )
auto grid = m_rigCaseData->grid( m_gridIndex );
if ( !grid ) return nullptr;
if ( m_showLgrMeshLines && RiaPreferencesGrid::current()->radialGridMode() == RiaGridDefines::RadialGridMode::CYLINDRICAL )
{
return createMeshDrawableFromLgrGridCells();
}
return cvf::StructGridGeometryGenerator::createMeshDrawableFromSingleCell( m_rigCaseData->grid( m_gridIndex ),
m_cellIndex,
m_displayModelOffset );
else
{
return cvf::StructGridGeometryGenerator::createMeshDrawableFromSingleCell( grid, m_cellIndex, m_displayModelOffset );
}
}
else if ( m_geoMechCase && m_cellIndex != cvf::UNDEFINED_SIZE_T )
{
@@ -138,108 +253,25 @@ cvf::ref<cvf::DrawableGeo> RivSingleCellPartGenerator::createMeshDrawableFromLgr
if ( !m_rigCaseData ) return nullptr;
if ( m_cellIndex == cvf::UNDEFINED_SIZE_T ) return nullptr;
auto currentGrid = m_rigCaseData->grid( m_gridIndex );
if ( !currentGrid ) return nullptr;
auto mainGrid = m_rigCaseData->mainGrid();
if ( !mainGrid ) return nullptr;
auto currentCell = currentGrid->cell( m_cellIndex );
auto cellIndexInMainGrid = currentCell.parentCellIndex();
if ( mainGrid->gridCount() < 2 ) return nullptr;
auto lgrGrid = m_rigCaseData->grid( 1 );
if ( !lgrGrid ) return nullptr;
std::vector<size_t> lgrCellIndices;
for ( size_t i = 0; i < currentGrid->cellCount(); i++ )
for ( size_t i = 0; i < lgrGrid->cellCount(); i++ )
{
const auto cell = currentGrid->cell( i );
const auto cell = lgrGrid->cell( i );
auto parentCellIndex = cell.parentCellIndex();
if ( parentCellIndex == cellIndexInMainGrid )
if ( parentCellIndex == m_cellIndex )
{
lgrCellIndices.push_back( i );
}
}
std::vector<cvf::Vec3d> quadVertices;
std::vector<cvf::Vec3d> lineVertexPairs;
for ( auto cellIndex : lgrCellIndices )
{
std::array<cvf::Vec3d, 8> cornerVerts = currentGrid->cellCornerVertices( cellIndex );
cvf::ubyte faceConn[4];
// Show grid lines for vertical lines along the radius of the cylinder segment
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::NEG_I, faceConn );
lineVertexPairs.push_back( cornerVerts[faceConn[1]] );
lineVertexPairs.push_back( cornerVerts[faceConn[2]] );
lineVertexPairs.push_back( cornerVerts[faceConn[3]] );
lineVertexPairs.push_back( cornerVerts[faceConn[0]] );
// Show grid lines for vertical lines along the radius of the cylinder segment
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::POS_I, faceConn );
lineVertexPairs.push_back( cornerVerts[faceConn[0]] );
lineVertexPairs.push_back( cornerVerts[faceConn[1]] );
lineVertexPairs.push_back( cornerVerts[faceConn[2]] );
lineVertexPairs.push_back( cornerVerts[faceConn[3]] );
// Show quad lines for min/max J faces
if ( cellIndex == lgrCellIndices.back() )
{
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::POS_J, faceConn );
quadVertices.push_back( cornerVerts[faceConn[0]] );
quadVertices.push_back( cornerVerts[faceConn[1]] );
quadVertices.push_back( cornerVerts[faceConn[2]] );
quadVertices.push_back( cornerVerts[faceConn[3]] );
}
if ( cellIndex == lgrCellIndices.front() )
{
RigGridBase::cellFaceVertexIndices( cvf::StructGridInterface::NEG_J, faceConn );
quadVertices.push_back( cornerVerts[faceConn[0]] );
quadVertices.push_back( cornerVerts[faceConn[1]] );
quadVertices.push_back( cornerVerts[faceConn[2]] );
quadVertices.push_back( cornerVerts[faceConn[3]] );
}
}
std::vector<cvf::Vec3f> displayVertices;
for ( const auto& v : quadVertices )
{
displayVertices.push_back( cvf::Vec3f( v - m_displayModelOffset ) );
}
cvf::ref<cvf::Vec3fArray> cvfVertices = new cvf::Vec3fArray;
cvfVertices->assign( displayVertices );
if ( !cvfVertices.notNull() || cvfVertices->size() == 0 ) return nullptr;
ref<UIntArray> indices = StructGridGeometryGenerator::lineIndicesFromQuadVertexArray( cvfVertices.p() );
// Add vertex pairs as lines
const auto quadVertexCount = cvfVertices->size();
const auto indicesCount = indices->size();
cvfVertices->resize( quadVertexCount + lineVertexPairs.size() );
indices->resize( indicesCount + lineVertexPairs.size() );
size_t iIndex = indicesCount;
size_t vIndex = quadVertexCount;
for ( const auto& v : lineVertexPairs )
{
indices->set( iIndex++, static_cast<cvf::uint>( vIndex ) );
cvfVertices->set( vIndex++, cvf::Vec3f( v - m_displayModelOffset ) );
}
ref<DrawableGeo> geo = new DrawableGeo;
geo->setVertexArray( cvfVertices.p() );
ref<PrimitiveSetIndexedUInt> prim = new PrimitiveSetIndexedUInt( PT_LINES );
prim->setIndices( indices.p() );
geo->addPrimitiveSet( prim.p() );
return geo;
return createMeshLinesOfParentGridCells( lgrGrid, lgrCellIndices, m_displayModelOffset );
}
@@ -27,6 +27,7 @@ class Part;
}
class RigEclipseCaseData;
class RigGridBase;
class RimGeoMechCase;
//==================================================================================================
@@ -41,7 +42,10 @@ public:
void setShowLgrMeshLines( bool enable );
cvf::ref<cvf::Part> createPart( const cvf::Color3f color );
cvf::ref<cvf::Part> createPart( const cvf::Color3f color );
static cvf::ref<cvf::DrawableGeo> createMeshLinesOfParentGridCells( RigGridBase const* grid,
std::vector<size_t>& localGridCellIndices,
const cvf::Vec3d& displayModelOffset );
private:
cvf::ref<cvf::DrawableGeo> createMeshDrawable();
@@ -181,9 +181,13 @@ void RimCellRangeFilter::computeAndSetValidValues()
//--------------------------------------------------------------------------------------------------
bool RimCellRangeFilter::isMainGridRadial() const
{
auto rimCase = firstAncestorOrThisOfTypeAsserted<Rim3dView>()->ownerCase();
auto rigGrid = dynamic_cast<const RigGridBase*>( selectedGrid() );
if ( !rigGrid ) return false;
return RigReservoirGridTools::isRadialGrid( rimCase );
auto mainGrid = rigGrid->mainGrid();
if ( !mainGrid ) return false;
return mainGrid->isRadial();
}
//--------------------------------------------------------------------------------------------------
@@ -43,6 +43,7 @@
#include "RigEclipseCaseData.h"
#include "RigFlowDiagSolverInterface.h"
#include "RigMainGrid.h"
#include "RigReservoirGridTools.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationTools.h"
@@ -298,6 +299,12 @@ bool RimEclipseResultCase::importGridAndResultMetaData( bool showTimeStepFilter
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->computeCellVolumes();
}
if ( mainGrid() && mainGrid()->isRadial() )
{
// This is required to make the generated LGR for radial grids work when loading a project file
RigReservoirGridTools::refreshEclipseCaseDataAndViews( this );
}
return true;
}
@@ -77,6 +77,22 @@ std::string RigGridBase::gridName() const
return m_gridName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigGridBase::isRadial() const
{
return m_isRadial;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigGridBase::setIsRadial( bool isRadial )
{
m_isRadial = isRadial;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -51,6 +51,9 @@ public:
cvf::Vec3st cellCounts() const { return m_cellCounts; }
virtual size_t cellCount() const { return m_cellCountIJK; }
bool isRadial() const;
void setIsRadial( bool isRadial );
virtual RigCell& cell( size_t gridLocalCellIndex );
virtual const RigCell& cell( size_t gridLocalCellIndex ) const;
@@ -128,6 +131,7 @@ private:
int m_gridId; ///< The LGR id of this grid. Main grid has id 0.
RigMainGrid* m_mainGrid;
cvf::BoundingBox m_boundingBox;
bool m_isRadial = false;
std::vector<std::array<size_t, 6>> m_coarseningBoxInfo;
};
@@ -108,26 +108,6 @@ QString RigReservoirGridTools::gridName( RimCase* rimCase, int gridIndex )
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigReservoirGridTools::isRadialGrid( RimCase* rimCase )
{
RimEclipseResultCase* eclipseResultCase = dynamic_cast<RimEclipseResultCase*>( rimCase );
if ( !eclipseResultCase ) return false;
auto eclipseCaseData = eclipseResultCase->eclipseCaseData();
if ( !eclipseCaseData ) return false;
auto results = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
if ( !results ) return false;
auto readerInterface = results->readerInterface();
if ( !readerInterface ) return false;
return readerInterface->isRadialGrid();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -47,7 +47,6 @@ public:
static const cvf::StructGridInterface* mainGrid( RimCase* rimCase );
static const cvf::StructGridInterface* gridByIndex( RimCase* rimCase, int gridIndex );
static QString gridName( RimCase* rimCase, int gridIndex );
static bool isRadialGrid( RimCase* rimCase );
static const RigActiveCellInfo* activeCellInfo( Rim3dView* rimView );
@@ -360,21 +360,59 @@ bool RiuCellAndNncPickEventHandler::handle3dPickEvent( const Ric3dPickEvent& eve
}
}
selItem = new RiuEclipseSelectionItem( associatedGridView,
eclResDef,
timestepIndex,
gridIndex,
gridLocalCellIndex,
nncIndex,
curveColor,
face,
localIntersectionPoint );
// The SHIFT button is used to toggle between showing mesh lines for LGR cells or main grid cells.
//
// The logic for clicking on a cell in a radial grid is as follows:
// - If SHIFT is not pressed, show mesh lines for the main grid cell
// - If SHIFT is pressed, show mesh lines for the LGR cells
//
// For non-radial grids, the logic is reversed:
// - If SHIFT is pressed, show mesh lines for the main grid cell
// - If SHIFT is not pressed, show mesh lines for the LGR cells
//
const bool isShiftPressed = ( keyboardModifiers & Qt::ShiftModifier ) != 0;
// Check if ctrl button is pressed
if ( keyboardModifiers & Qt::ShiftModifier )
bool showLgrMeshLines = false;
auto eclipseView = dynamic_cast<RimEclipseView*>( mainOrComparisonView );
auto mainGrid = eclipseView->eclipseCase()->eclipseCaseData()->mainGrid();
auto currentGrid = mainGrid->gridByIndex( gridIndex );
if ( mainGrid && !currentGrid->isMainGrid() )
{
static_cast<RiuEclipseSelectionItem*>( selItem )->setShowLgrMeshLines( true );
bool selectMainGridCell = false;
if ( currentGrid->isRadial() )
{
selectMainGridCell = !isShiftPressed;
showLgrMeshLines = !isShiftPressed;
}
else
{
selectMainGridCell = isShiftPressed;
}
if ( selectMainGridCell )
{
auto currentGrid = mainGrid->gridByIndex( gridIndex );
const auto cellIndexInMainGrid = currentGrid->cell( gridLocalCellIndex ).parentCellIndex();
// Change selection to main grid cell
gridIndex = mainGrid->gridIndex();
gridLocalCellIndex = cellIndexInMainGrid;
}
}
auto eclSelectionItem = new RiuEclipseSelectionItem( associatedGridView,
eclResDef,
timestepIndex,
gridIndex,
gridLocalCellIndex,
nncIndex,
curveColor,
face,
localIntersectionPoint );
eclSelectionItem->setShowLgrMeshLines( showLgrMeshLines );
selItem = eclSelectionItem;
}
if ( geomResDef )