mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 15:10:22 -05:00
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:
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;
|
||||
}
|
||||
Reference in new issue
Block a user