Support radial grids as cylindrical cells

* Add minimum angular count to system preferences
* Refactors grid view updates and radial grid handling
* Improves radial grid handling and LGR creation
This commit is contained in:
Magne Sjaastad authored and GitHub committed 2025-09-24 09:46:00 +02:00
1 parent d494725da8
commit 6ef5db2530
14 files changed
+479 -137

No files matched your search

@@ -77,6 +77,11 @@ 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)" );
CAF_PDM_InitField( &m_exportScalingFactor, "exportScalingFactor", -1.0, "Export Scaling Factor (<0 disable)" );
@@ -239,6 +244,22 @@ std::optional<int> RiaPreferencesSystem::threadCount() const
return text.toInt();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaPreferencesSystem::useCylindricalCoordinates() const
{
return m_useCylindricalCoordinates();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RiaPreferencesSystem::minimumAngularCellCount() const
{
return m_mimimumAngularCellCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -289,6 +310,12 @@ void RiaPreferencesSystem::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd
uiOrdering.add( &m_exportScalingFactor );
uiOrdering.add( &m_eclipseReaderMode );
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Radial Grid" );
group->add( &m_useCylindricalCoordinates );
group->add( &m_mimimumAngularCellCount );
}
{
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Developer Settings" );
group->add( &m_keywordsForLogging );
@@ -59,6 +59,9 @@ public:
std::optional<int> threadCount() const;
bool useCylindricalCoordinates() const;
int minimumAngularCellCount() const;
EclipseTextFileReaderMode eclipseTextFileReaderMode() const;
bool isLoggingActivatedForKeyword( const QString& keyword ) const;
@@ -84,7 +87,11 @@ private:
caf::PdmField<bool> m_showPdfExportDialog;
caf::PdmField<double> m_exportScalingFactor;
caf::PdmField<bool> m_showProgressBar;
caf::PdmField<bool> m_showProgressBar;
caf::PdmField<bool> m_useCylindricalCoordinates;
caf::PdmField<int> m_mimimumAngularCellCount;
caf::PdmField<QString> m_gtestFilter;
caf::PdmField<EclipseTextFileReaderModeType> m_eclipseReaderMode;
@@ -18,6 +18,9 @@
#include "RicfCreateLgrForCompletions.h"
#include "RiaLogging.h"
#include "RiaWellNameComparer.h"
#include "RicfApplicationTools.h"
#include "RicfCommandFileExecutor.h"
@@ -25,6 +28,8 @@
#include "RicCreateTemporaryLgrFeature.h"
#include "RicDeleteTemporaryLgrsFeature.h"
#include "RigReservoirGridTools.h"
#include "RimDialogData.h"
#include "RimEclipseCase.h"
#include "RimEclipseCaseCollection.h"
@@ -33,9 +38,6 @@
#include "RimProject.h"
#include "RimWellPath.h"
#include "RiaLogging.h"
#include "RiaWellNameComparer.h"
#include "cafCmdFeatureManager.h"
#include "cafPdmFieldScriptingCapability.h"
@@ -121,7 +123,7 @@ caf::PdmScriptResponse RicfCreateLgrForCompletions::execute()
RigCompletionData::CompletionType::FISHBONES },
&wellsIntersectingOtherLgrs );
feature->updateViews( eclipseCase );
RigReservoirGridTools::refreshEclipseCaseDataAndViews( eclipseCase );
caf::PdmScriptResponse response;
if ( !wellsIntersectingOtherLgrs.empty() )
@@ -31,6 +31,7 @@
#include "RigCell.h"
#include "RigEclipseCaseData.h"
#include "RigMainGrid.h"
#include "RigReservoirGridTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
@@ -84,36 +85,6 @@ void RicCreateTemporaryLgrFeature::createLgrsForWellPaths( std::vector<RimWellPa
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateTemporaryLgrFeature::updateViews( RimEclipseCase* eclipseCase )
{
RiaGuiApplication* guiApp = nullptr;
if ( RiaGuiApplication::isRunning() )
{
guiApp = RiaGuiApplication::instance();
}
if ( guiApp ) RiaGuiApplication::clearAllSelections();
deleteAllCachedData( eclipseCase );
RimMainPlotCollection::current()->deleteAllCachedData();
computeCachedData( eclipseCase );
for ( auto view : eclipseCase->reservoirViews() )
{
if ( view && view->gridCollection() )
{
view->gridCollection()->syncFromMainEclipseGrid();
}
}
RimMainPlotCollection::current()->wellLogPlotCollection()->loadDataAndUpdateAllPlots();
if ( guiApp ) eclipseCase->createDisplayModelAndUpdateAllViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -159,7 +130,7 @@ void RicCreateTemporaryLgrFeature::onActionTriggered( bool isChecked )
createLgrsForWellPaths( wellPaths, eclipseCase, timeStep, refinement, splitType, completionTypes, &wellsIntersectingOtherLgrs );
updateViews( eclipseCase );
RigReservoirGridTools::refreshEclipseCaseDataAndViews( eclipseCase );
if ( !wellsIntersectingOtherLgrs.empty() )
{
@@ -183,7 +154,7 @@ void RicCreateTemporaryLgrFeature::setupActionLook( QAction* actionToSetup )
//--------------------------------------------------------------------------------------------------
/// Todo: Guarding, caching LGR corner nodes calculations
//--------------------------------------------------------------------------------------------------
void RicCreateTemporaryLgrFeature::createLgr( const LgrInfo& lgrInfo, RigMainGrid* mainGrid )
RigGridBase* RicCreateTemporaryLgrFeature::createLgr( const LgrInfo& lgrInfo, RigMainGrid* mainGrid )
{
int lgrId = lgrInfo.id;
size_t totalCellCount = mainGrid->totalCellCount();
@@ -260,64 +231,55 @@ void RicCreateTemporaryLgrFeature::createLgr( const LgrInfo& lgrInfo, RigMainGri
}
localGrid->setParentGrid( mainGrid );
return localGrid;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateTemporaryLgrFeature::deleteAllCachedData( RimEclipseCase* eclipseCase )
RigGridBase* RicCreateTemporaryLgrFeature::createLgr( const LgrInfo& lgrInfo, RigEclipseCaseData* caseData )
{
if ( eclipseCase )
auto mainGrid = caseData->mainGrid();
auto gridCount = mainGrid->gridCount();
auto mainGridCellCount = mainGrid->totalCellCount();
auto localGrid = createLgr( lgrInfo, mainGrid );
if ( auto activeInfo = caseData->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL ) )
{
std::vector<RiaDefines::ResultCatType> categoriesToExclude = { RiaDefines::ResultCatType::GENERATED };
auto currentReservoirCellCount = activeInfo->reservoirCellCount();
RigCaseCellResultsData* cellResultsDataMatrix = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
if ( cellResultsDataMatrix )
activeInfo->setGridCount( gridCount + 1 );
activeInfo->setReservoirCellCount( currentReservoirCellCount + localGrid->cellCount() );
size_t activeCellCount = 0;
for ( size_t k = 0; k < localGrid->cellCountK(); k++ )
{
cellResultsDataMatrix->freeAllocatedResultsData( categoriesToExclude, std::nullopt );
for ( size_t j = 0; j < localGrid->cellCountJ(); j++ )
{
for ( size_t i = 0; i < localGrid->cellCountI(); i++ )
{
size_t cellIndex = localGrid->cellIndexFromIJK( i, j, k );
auto gridCell = localGrid->cell( cellIndex );
if ( gridCell.parentCellIndex() != cvf::UNDEFINED_SIZE_T )
{
auto resultIndex = activeInfo->cellResultIndex( gridCell.parentCellIndex() );
if ( resultIndex != cvf::UNDEFINED_SIZE_T )
{
activeInfo->setCellResultIndex( cellIndex + mainGridCellCount, resultIndex );
activeCellCount++;
}
}
}
}
}
RigCaseCellResultsData* cellResultsDataFracture = eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL );
if ( cellResultsDataFracture )
{
cellResultsDataFracture->freeAllocatedResultsData( categoriesToExclude, std::nullopt );
}
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
if ( eclipseCaseData )
{
eclipseCaseData->clearWellCellsInGridCache();
eclipseCaseData->setVirtualPerforationTransmissibilities( nullptr );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateTemporaryLgrFeature::computeCachedData( RimEclipseCase* eclipseCase )
{
if ( eclipseCase )
{
RigCaseCellResultsData* cellResultsDataMatrix = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
RigCaseCellResultsData* cellResultsDataFracture = eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL );
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
if ( eclipseCaseData )
{
eclipseCaseData->mainGrid()->computeCachedData();
eclipseCase->computeActiveCellsBoundingBox();
}
if ( cellResultsDataMatrix )
{
cellResultsDataMatrix->computeDepthRelatedResults();
cellResultsDataMatrix->computeCellVolumes();
}
if ( cellResultsDataFracture )
{
cellResultsDataFracture->computeDepthRelatedResults();
}
activeInfo->setGridActiveCellCounts( gridCount, activeCellCount );
activeInfo->computeDerivedData();
}
return localGrid;
}
@@ -30,13 +30,10 @@
class LgrInfo;
class RigMainGrid;
class RigCell;
class RimEclipseCase;
class RimSimWellInView;
class RimWellPath;
class RicExportLgrUi;
class QFile;
class QTextStream;
class RigGridBase;
class RigEclipseCaseData;
//==================================================================================================
///
@@ -54,16 +51,11 @@ public:
const std::set<RigCompletionData::CompletionType>& completionTypes,
QStringList* wellsIntersectingOtherLgrs );
void updateViews( RimEclipseCase* eclipseCase );
static void createLgr( const LgrInfo& lgrInfo, RigMainGrid* mainGrid );
static RigGridBase* createLgr( const LgrInfo& lgrInfo, RigEclipseCaseData* caseData );
static RigGridBase* createLgr( const LgrInfo& lgrInfo, RigMainGrid* mainGrid );
protected:
bool isCommandEnabled() const override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
void computeCachedData( RimEclipseCase* eclipseCase );
void deleteAllCachedData( RimEclipseCase* eclipseCase );
};
@@ -18,9 +18,14 @@
#include "RifOpmRadialGridTools.h"
#include "RiaAngleUtils.h"
#include "RiaLogging.h"
#include "RiaPreferencesSystem.h"
#include "RiaWeightedMeanCalculator.h"
#include "ExportCommands/RicExportLgrFeature.h"
#include "RicCreateTemporaryLgrFeature.h"
#include "RifReaderEclipseOutput.h"
#include "RigActiveCellInfo.h"
@@ -37,8 +42,9 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
bool RifOpmRadialGridTools::importCylindricalCoordinates( const std::string& gridFilePath, RigEclipseCaseData* caseData )
{
auto riMainGrid = caseData->mainGrid();
CAF_ASSERT( riMainGrid );
try
@@ -67,7 +73,74 @@ void RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& g
}
}
if ( !isRadialGridPresent ) return;
if ( !isRadialGridPresent ) return false;
bool lgrIsCreated = false;
Opm::EclIO::EGrid opmMainGrid( gridFilePath );
if ( opmMainGrid.is_radial() )
{
transferCylindricalCoords( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
auto minimumAngularCellCount = RiaPreferencesSystem::current()->minimumAngularCellCount();
if ( opmMainGrid.is_radial() && opmMainGrid.dimension().at( 1 ) < minimumAngularCellCount )
{
RiaLogging::info( QString( "Radial grid with less than 4 cells in J direction detected, creating refinement : %1" )
.arg( QString::fromStdString( gridFilePath ) ) );
int radialRefinement = ( minimumAngularCellCount / opmMainGrid.dimension().at( 1 ) ) + 1;
createAngularGridRefinement( caseData, radialRefinement );
lgrIsCreated = true;
}
}
return lgrIsCreated;
}
catch ( ... )
{
RiaLogging::warning(
QString( "Failed to open grid case for import of radial coordinates : %1" ).arg( QString::fromStdString( gridFilePath ) ) );
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
{
try
{
auto isRadialGrid = []( const std::string& gridFilePath )
{
// Open the file and only check "GRIDHEAD" to be able to do an early return if no radial grids are present
Opm::EclIO::EclFile gridFile( gridFilePath );
auto arrays = gridFile.getList();
int index = 0;
for ( const auto& [name, arrayType, arraySize] : arrays )
{
if ( name == "GRIDHEAD" )
{
auto gridhead = gridFile.get<int>( index );
if ( gridhead.size() > 26 && gridhead[26] > 0 )
{
return true;
}
}
index++;
}
return false;
};
if ( !isRadialGrid( gridFilePath ) ) return false;
Opm::EclIO::EGrid opmMainGrid( gridFilePath );
@@ -99,6 +172,8 @@ void RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& g
RiaLogging::warning(
QString( "Failed to open grid case for import of radial coordinates : %1" ).arg( QString::fromStdString( gridFilePath ) ) );
}
return true;
}
//--------------------------------------------------------------------------------------------------
@@ -127,10 +202,55 @@ void RifOpmRadialGridTools::importCoordinatesForRadialGrid( const std::string& g
// ||---------||
// -------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmRadialGridTools::transferCylindricalCoords( Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
RigMainGrid* riMainGrid,
RigGridBase* riGrid )
{
size_t cellCount = opmGrid.totalNumberOfCells();
if ( cellCount != riGrid->cellCount() ) return;
// Read out the corner coordinates from the EGRID file using cylindrical coordinates.
// Prefix OPM structures with _opm_and ResInsight structures with _ri_
std::array<double, 8> opmX{};
std::array<double, 8> opmY{};
std::array<double, 8> opmZ{};
const auto hostCellGlobalIndices = opmGrid.hostCellsGlobalIndex();
const size_t* cellMappingECLRi = RifReaderEclipseOutput::eclipseCellIndexMapping();
auto& riNodes = riMainGrid->nodes();
bool convertCylindricalCoords = false;
for ( int opmCellIndex = 0; opmCellIndex < static_cast<int>( cellCount ); opmCellIndex++ )
{
auto ijkCell = opmGrid.ijk_from_global_index( opmCellIndex );
opmGrid.getCellCorners( ijkCell, opmX, opmY, opmZ, convertCylindricalCoords );
// Each cell has 8 nodes, use reservoir cell index and multiply to find first node index for cell
auto riNodeStartIndex = riGrid->reservoirCellIndex( opmCellIndex ) * 8;
for ( size_t opmNodeIndex = 0; opmNodeIndex < 8; opmNodeIndex++ )
{
size_t riNodeIndex = riNodeStartIndex + cellMappingECLRi[opmNodeIndex];
// The radial grid is specified with (0,0) as center, add grid center to get correct global coordinates
auto& riNode = riNodes[riNodeIndex];
riNode.x() = opmX[opmNodeIndex];
riNode.y() = opmY[opmNodeIndex];
riNode.z() = -opmZ[opmNodeIndex];
}
}
}
//--------------------------------------------------------------------------------------------------
// 1. If the node is at the outer edge of the radial grid, find the host cell
// 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,
@@ -155,8 +275,6 @@ void RifOpmRadialGridTools::transferCoordinatesRadial( Opm::EclIO::EGrid& opmMai
const auto gridDimension = opmGrid.dimension();
auto& riNodes = riMainGrid->nodes();
std::vector<cvf::Vec3d> snapToCoordinatesFromMainGrid;
for ( int opmCellIndex = 0; opmCellIndex < static_cast<int>( cellCount ); opmCellIndex++ )
{
opmGrid.getCellCorners( opmCellIndex, opmX, opmY, opmZ );
@@ -280,6 +398,49 @@ void RifOpmRadialGridTools::lockToHostPillars( cvf::Vec3d& riNode,
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifOpmRadialGridTools::createAngularGridRefinement( RigEclipseCaseData* caseData, size_t angularRefinement )
{
if ( !caseData || !caseData->mainGrid() ) return false;
auto riMainGrid = caseData->mainGrid();
const int id = 100;
const int nRadial = 1;
const int nK = 1;
const caf::VecIjk mainGridStart( 0, 0, 0 );
const caf::VecIjk mainGridEnd( riMainGrid->cellCountI() - 1, riMainGrid->cellCountJ() - 1, riMainGrid->cellCountK() - 1 );
const caf::VecIjk refinement( nRadial, angularRefinement, nK );
LgrInfo lgrInfo{ id, "Radial LGR", "", refinement, mainGridStart, mainGridEnd };
RicCreateTemporaryLgrFeature::createLgr( lgrInfo, caseData );
// Convert the radial grid to a Cartesian grid
std::vector<cvf::Vec3d>& nodes = riMainGrid->nodes();
convertNodesToCartesian( nodes );
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOpmRadialGridTools::convertNodesToCartesian( std::vector<cvf::Vec3d>& nodes )
{
for ( size_t i = 0; i < nodes.size(); i++ )
{
auto& node = nodes[i];
auto cartesian = Ria::CoordinateConverter::cylindricalToCartesian( node.x(), Ria::Degreesd( node.y() ), node.z() );
node.x() = cartesian.x();
node.y() = cartesian.y();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -43,17 +43,13 @@ class RifOpmRadialGridTools
{
public:
// If the grid is radial, the coordinates are imported and adjusted to fit the host cells
static void importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
static bool importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* mainGrid );
static void
transferCoordinatesRadial( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigMainGrid* riMainGrid, RigGridBase* riGrid );
static bool importCylindricalCoordinates( const std::string& gridFilePath, RigEclipseCaseData* caseData );
static std::map<int, std::pair<double, double>>
computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, RigGridBase* riGrid );
static std::vector<std::vector<cvf::Vec3d>>
computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex );
static void lockToHostPillars( cvf::Vec3d& riNode,
Opm::EclIO::EGrid& opmMainGrid,
Opm::EclIO::EGrid& opmGrid,
@@ -63,4 +59,17 @@ public:
size_t opmNodeIndex,
double xCenterCoordOpm,
double yCenterCoordOpm );
static bool createAngularGridRefinement( RigEclipseCaseData* caseData, size_t angularRefinement );
static void convertNodesToCartesian( std::vector<cvf::Vec3d>& nodes );
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 std::vector<std::vector<cvf::Vec3d>>
computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid, Opm::EclIO::EGrid& opmGrid, int mainGridCellIndex, int lgrCellIndex );
};
@@ -31,7 +31,6 @@
#include "RifEclipseRestartDataAccess.h"
#include "RifEdfmTools.h"
#include "RifHdf5ReaderInterface.h"
#include "RifOpmRadialGridTools.h"
#include "RifReaderEclipseWell.h"
#ifdef USE_HDF5
@@ -399,8 +398,6 @@ bool RifReaderEclipseOutput::open( const QString& fileName, RigEclipseCaseData*
{
auto task = progress.task( "Transferring grid geometry", 10 );
if ( !transferGeometry( mainEclGrid, eclipseCaseData, invalidateLongThinCells() ) ) return false;
RifOpmRadialGridTools::importCoordinatesForRadialGrid( fileName.toStdString(), eclipseCaseData->mainGrid() );
}
auto iLimitFromEdfm = RifEdfmTools::checkForEdfmLimitI( fileName );
@@ -24,6 +24,7 @@
#include "RiaFieldHandleTools.h"
#include "RiaLogging.h"
#include "RiaPreferencesGrid.h"
#include "RiaPreferencesSystem.h"
#include "RiaRegressionTestRunner.h"
#include "RiaResultNames.h"
@@ -32,6 +33,7 @@
#include "RifEclipseOutputFileTools.h"
#include "RifEclipseRestartDataAccess.h"
#include "RifInputPropertyLoader.h"
#include "RifOpmRadialGridTools.h"
#include "RifReaderEclipseOutput.h"
#include "RifReaderEclipseRft.h"
#include "RifReaderMockModel.h"
@@ -43,6 +45,7 @@
#include "RigEclipseCaseData.h"
#include "RigFlowDiagSolverInterface.h"
#include "RigMainGrid.h"
#include "RigReservoirGridTools.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationTools.h"
@@ -150,6 +153,49 @@ bool RimEclipseResultCase::showTimeStepFilterGUI()
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseResultCase::checkAndImportRadialGrid()
{
bool refreshEclipseCaseData = false;
if ( RiaPreferencesSystem::current()->useCylindricalCoordinates() )
{
// Check if radial grid data is available. Create LGR if radial section count is below specified limit. Rebuild cached data if
// required.
bool isLgrCreated = RifOpmRadialGridTools::importCylindricalCoordinates( gridFileName().toStdString(), eclipseCaseData() );
if ( !isLgrCreated )
{
// 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
auto bb = mainGrid()->boundingBox();
const double epsilon = 1.0;
if ( ( std::abs( bb.min().y() ) < epsilon ) && ( std::abs( bb.max().y() - 360.0 ) < epsilon ) )
{
size_t minimumAngularCellCount = static_cast<size_t>( RiaPreferencesSystem::current()->minimumAngularCellCount() );
if ( mainGrid()->cellCountJ() < minimumAngularCellCount )
{
auto angularRefinement = ( minimumAngularCellCount / mainGrid()->cellCountJ() ) + 1;
isLgrCreated = RifOpmRadialGridTools::createAngularGridRefinement( eclipseCaseData(), angularRefinement );
}
}
}
refreshEclipseCaseData = isLgrCreated;
}
else
{
refreshEclipseCaseData =
RifOpmRadialGridTools::importCoordinatesForRadialGrid( gridFileName().toStdString(), eclipseCaseData()->mainGrid() );
}
if ( refreshEclipseCaseData )
{
RigReservoirGridTools::refreshEclipseCaseDataAndViews( this );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -297,6 +343,9 @@ bool RimEclipseResultCase::importGridAndResultMetaData( bool showTimeStepFilter
results( RiaDefines::PorosityModelType::MATRIX_MODEL )->computeCellVolumes();
}
checkAndImportRadialGrid();
return true;
}
@@ -545,8 +594,8 @@ cvf::ref<RifReaderInterface> RimEclipseResultCase::createMockModel( QString mode
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase::~RimEclipseResultCase()
{
// Disconnect all comparison views. In debug build on Windows, a crash occurs. The comparison view is also set to zero in the destructor
// of Rim3dView()
// Disconnect all comparison views. In debug build on Windows, a crash occurs. The comparison view is also set to zero in the
// destructor of Rim3dView()
for ( auto v : reservoirViews() )
{
if ( v ) v->setComparisonView( nullptr );
@@ -89,6 +89,7 @@ private:
void loadAndUpdateSourSimData();
void ensureRftDataIsImported();
bool showTimeStepFilterGUI();
void checkAndImportRadialGrid();
cvf::ref<RifReaderInterface> createMockModel( QString modelName );
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
@@ -369,6 +369,12 @@ cvf::ref<RigResultAccessor> RigResultAccessorFactory::createNativeFromResultAddr
}
bool useGlobalActiveIndex = eclipseCase->results( porosityModel )->isUsingGlobalActiveIndex( resultAddress );
if ( eclipseCase->mainGrid()->gridCount() > 1 )
{
// Always use active cell indexing for multi-grid cases. If all cells in the main grid is active, and a local grid is created, this
// option must be set to true
useGlobalActiveIndex = true;
}
if ( useGlobalActiveIndex )
{
cvf::ref<RigResultAccessor> object =
@@ -741,6 +741,30 @@ void RigEclipseCaseData::computeActiveCellsGeometryBoundingBoxOptimized()
}
}
if ( m_mainGrid->totalTemporaryGridCellCount() > 0 )
{
// When we have LGRs for radial grids, we must loop over all local grids. The local grids can contain coordinates not present
// in the main grid
for ( size_t i = 0; i < m_mainGrid->gridCount(); i++ )
{
auto localGrid = m_mainGrid->gridByIndex( i );
for ( size_t localCellIndex = 0; localCellIndex < localGrid->cellCount(); localCellIndex++ )
{
size_t globalCellIndex = localGrid->reservoirCellIndex( localCellIndex );
if ( globalCellIndex < activeInfos[acIdx]->reservoirCellCount() && activeInfos[acIdx]->isActive( globalCellIndex ) )
{
std::array<cvf::Vec3d, 8> hexCorners = localGrid->cellCornerVertices( localCellIndex );
for ( const auto& corner : hexCorners )
{
bb.add( corner );
}
}
}
}
}
activeInfos[acIdx]->setGeometryBoundingBox( bb );
}
@@ -18,7 +18,10 @@
#include "RigReservoirGridTools.h"
#include "RiaGuiApplication.h"
#include "RigActiveCellInfo.h"
#include "RigCaseCellResultsData.h"
#include "RigEclipseCaseData.h"
#include "RigFemPartCollection.h"
#include "RigFemPartGrid.h"
@@ -28,6 +31,9 @@
#include "RimEclipseCase.h"
#include "RimEclipseView.h"
#include "RimGeoMechCase.h"
#include "RimGridCollection.h"
#include "RimMainPlotCollection.h"
#include "RimWellLogPlotCollection.h"
#include <QString>
@@ -113,6 +119,36 @@ const RigActiveCellInfo* RigReservoirGridTools::activeCellInfo( Rim3dView* rimVi
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigReservoirGridTools::refreshEclipseCaseDataAndViews( RimEclipseCase* eclipseCase )
{
RiaGuiApplication* guiApp = nullptr;
if ( RiaGuiApplication::isRunning() )
{
guiApp = RiaGuiApplication::instance();
}
if ( guiApp ) RiaGuiApplication::clearAllSelections();
deleteAllCachedData( eclipseCase );
RimMainPlotCollection::current()->deleteAllCachedData();
computeCachedData( eclipseCase );
for ( auto view : eclipseCase->reservoirViews() )
{
if ( view && view->gridCollection() )
{
view->gridCollection()->syncFromMainEclipseGrid();
}
}
RimMainPlotCollection::current()->wellLogPlotCollection()->loadDataAndUpdateAllPlots();
if ( guiApp ) eclipseCase->createDisplayModelAndUpdateAllViews();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -140,3 +176,61 @@ RigFemPartCollection* RigReservoirGridTools::geoMechPartCollection( RimCase* rim
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigReservoirGridTools::computeCachedData( RimEclipseCase* eclipseCase )
{
if ( !eclipseCase ) return;
RigCaseCellResultsData* cellResultsDataMatrix = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
RigCaseCellResultsData* cellResultsDataFracture = eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL );
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
if ( eclipseCaseData )
{
eclipseCaseData->mainGrid()->computeCachedData();
eclipseCase->computeActiveCellsBoundingBox();
}
if ( cellResultsDataMatrix )
{
cellResultsDataMatrix->computeDepthRelatedResults();
cellResultsDataMatrix->computeCellVolumes();
}
if ( cellResultsDataFracture )
{
cellResultsDataFracture->computeDepthRelatedResults();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RigReservoirGridTools::deleteAllCachedData( RimEclipseCase* eclipseCase )
{
if ( !eclipseCase ) return;
std::vector<RiaDefines::ResultCatType> categoriesToExclude = { RiaDefines::ResultCatType::GENERATED };
RigCaseCellResultsData* cellResultsDataMatrix = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
if ( cellResultsDataMatrix )
{
cellResultsDataMatrix->freeAllocatedResultsData( categoriesToExclude, std::nullopt );
}
RigCaseCellResultsData* cellResultsDataFracture = eclipseCase->results( RiaDefines::PorosityModelType::FRACTURE_MODEL );
if ( cellResultsDataFracture )
{
cellResultsDataFracture->freeAllocatedResultsData( categoriesToExclude, std::nullopt );
}
RigEclipseCaseData* eclipseCaseData = eclipseCase->eclipseCaseData();
if ( eclipseCaseData )
{
eclipseCaseData->clearWellCellsInGridCache();
eclipseCaseData->setVirtualPerforationTransmissibilities( nullptr );
}
}
@@ -27,6 +27,7 @@ class RigFemPartCollection;
class RigMainGrid;
class RimCase;
class Rim3dView;
class RimEclipseCase;
namespace cvf
{
@@ -50,33 +51,43 @@ public:
static const RigActiveCellInfo* activeCellInfo( Rim3dView* rimView );
template <class InputIterator>
static QString globalCellIndicesToOneBasedIJKText( InputIterator first, InputIterator last, const RigMainGrid* mainGrid )
{
QString txt;
static QString globalCellIndicesToOneBasedIJKText( InputIterator first, InputIterator last, const RigMainGrid* mainGrid );
if ( mainGrid )
{
while ( first != last )
{
size_t globalCellIndex = *first;
size_t i, j, k;
mainGrid->ijkFromCellIndex( globalCellIndex, &i, &j, &k );
i++;
j++;
k++;
QString itemText = QString( "%1 %2 %3" ).arg( i ).arg( j ).arg( k );
txt += itemText + "\n";
++first;
}
}
return txt;
}
static void refreshEclipseCaseDataAndViews( RimEclipseCase* eclipseCase );
private:
static RigMainGrid* eclipseMainGrid( RimCase* rimCase );
static RigFemPartCollection* geoMechPartCollection( RimCase* rimCase );
static void computeCachedData( RimEclipseCase* eclipseCase );
static void deleteAllCachedData( RimEclipseCase* eclipseCase );
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <class InputIterator>
QString RigReservoirGridTools::globalCellIndicesToOneBasedIJKText( InputIterator first, InputIterator last, const RigMainGrid* mainGrid )
{
QString txt;
if ( mainGrid )
{
while ( first != last )
{
size_t globalCellIndex = *first;
size_t i, j, k;
mainGrid->ijkFromCellIndex( globalCellIndex, &i, &j, &k );
i++;
j++;
k++;
QString itemText = QString( "%1 %2 %3" ).arg( i ).arg( j ).arg( k );
txt += itemText + "\n";
++first;
}
}
return txt;
}