mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Add support for radial grids
* Update radial grid operations in submodule * Optionally display cell center and cell corners when clicking on cell * Add support for import of radial grids * Modify node coordinates to match host cell
This commit is contained in:
parent
4615d0b524
commit
b3a56a9353
@ -77,6 +77,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@ -155,6 +156,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifRftSegment.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifPressureDepthTextFileReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderPressureDepthData.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifOpmGridTools.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
402
ApplicationLibCode/FileInterface/RifOpmGridTools.cpp
Normal file
402
ApplicationLibCode/FileInterface/RifOpmGridTools.cpp
Normal file
@ -0,0 +1,402 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023- 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 "RifOpmGridTools.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaWeightedMeanCalculator.h"
|
||||
|
||||
#include "RifReaderEclipseOutput.h"
|
||||
|
||||
#include "RigMainGrid.h"
|
||||
|
||||
#include "cvfGeometryTools.h"
|
||||
|
||||
#include "opm/io/eclipse/EGrid.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifOpmGridTools::importCoordinatesForRadialGrid( const std::string& gridFilePath, RigMainGrid* riMainGrid )
|
||||
{
|
||||
CAF_ASSERT( riMainGrid );
|
||||
|
||||
try
|
||||
{
|
||||
bool isRadialGridPresent = false;
|
||||
|
||||
{
|
||||
// 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 )
|
||||
{
|
||||
isRadialGridPresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isRadialGridPresent ) return;
|
||||
|
||||
Opm::EclIO::EGrid opmMainGrid( gridFilePath );
|
||||
|
||||
if ( opmMainGrid.is_radial() )
|
||||
{
|
||||
transferCoordinates( opmMainGrid, opmMainGrid, riMainGrid, riMainGrid );
|
||||
}
|
||||
|
||||
auto lgrNames = opmMainGrid.list_of_lgrs();
|
||||
for ( const auto& lgrName : lgrNames )
|
||||
{
|
||||
Opm::EclIO::EGrid opmLgrGrid( gridFilePath, lgrName );
|
||||
|
||||
if ( opmLgrGrid.is_radial() )
|
||||
{
|
||||
for ( size_t i = 0; i < riMainGrid->gridCount(); i++ )
|
||||
{
|
||||
auto riLgrGrid = riMainGrid->gridByIndex( i );
|
||||
if ( riLgrGrid->gridName() == lgrName )
|
||||
{
|
||||
transferCoordinates( opmMainGrid, opmLgrGrid, riMainGrid, riLgrGrid );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
RiaLogging::warning( QString( "Failed to open grid case for import of radial coordinates : %1" )
|
||||
.arg( QString::fromStdString( gridFilePath ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// A radial grid is defined by a center point and a set of cylindrical coordinates. The coordinates at the
|
||||
// outer edge of the grid are defined as a circle, and nodes do not match the geometry of the host cell.
|
||||
// Adjust the coordinates for these cells to make sure the grid is continuous
|
||||
//
|
||||
// Cylindrical coordinates from file gives grid cell with a radial grid in center
|
||||
// -------------
|
||||
// | /---- \ |
|
||||
// | / - \ |
|
||||
// || | | ||
|
||||
// | \ - / |
|
||||
// | \-----/ |
|
||||
// -------------
|
||||
|
||||
//
|
||||
// Adjusted coordinates to match the grid geometry of host cell. The coordinates for the inner nodes are
|
||||
// unchanged.
|
||||
// -------------
|
||||
// ||---------||
|
||||
// || - ||
|
||||
// || | | ||
|
||||
// || - ||
|
||||
// ||---------||
|
||||
// -------------
|
||||
|
||||
// 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 RifOpmGridTools::transferCoordinates( 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 radial coordinates.
|
||||
// Prefix OPM structures with _opm_and ResInsight structures with _ri_
|
||||
|
||||
// Compute the center of the LGR radial grid cells for each K layer
|
||||
std::map<int, std::pair<double, double>> radialGridCenterTopLayerOpm =
|
||||
computeXyCenterForTopOfCells( opmMainGrid, opmGrid, riGrid );
|
||||
|
||||
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();
|
||||
const auto gridDimension = opmGrid.dimension();
|
||||
auto& riNodes = riMainGrid->nodes();
|
||||
|
||||
std::vector<cvf::Vec3d> snapToCoordinatesFromMainGrid;
|
||||
|
||||
for ( size_t opmCellIndex = 0; opmCellIndex < cellCount; opmCellIndex++ )
|
||||
{
|
||||
opmGrid.getCellCorners( opmCellIndex, opmX, opmY, opmZ );
|
||||
|
||||
// Each cell has 8 nodes, use reservoir cell index and multiply to find first node index for cell
|
||||
auto riNodeStartIndex = riGrid->reservoirCellIndex( opmCellIndex ) * 8;
|
||||
auto ijkCell = opmGrid.ijk_from_global_index( opmCellIndex );
|
||||
|
||||
double xCenterCoordOpm = 0.0;
|
||||
double yCenterCoordOpm = 0.0;
|
||||
|
||||
if ( radialGridCenterTopLayerOpm.count( ijkCell[2] ) > 0 )
|
||||
{
|
||||
const auto& [xCenter, yCenter] = radialGridCenterTopLayerOpm[ijkCell[2]];
|
||||
xCenterCoordOpm = xCenter;
|
||||
yCenterCoordOpm = yCenter;
|
||||
}
|
||||
|
||||
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] + xCenterCoordOpm;
|
||||
riNode.y() = opmY[opmNodeIndex] + yCenterCoordOpm;
|
||||
riNode.z() = -opmZ[opmNodeIndex];
|
||||
|
||||
// First grid dimension is radius, check if cell has are at the outer-most slice
|
||||
if ( !hostCellGlobalIndices.empty() && ( gridDimension[0] - 1 == ijkCell[0] ) )
|
||||
{
|
||||
std::array<double, 8> cellRadius{};
|
||||
std::array<double, 8> cellTheta{};
|
||||
std::array<double, 8> cellZ{};
|
||||
opmGrid.getRadialCellCorners( ijkCell, cellRadius, cellTheta, cellZ );
|
||||
|
||||
double maxRadius = *std::max_element( cellRadius.begin(), cellRadius.end() );
|
||||
|
||||
// Check if the radius is at the outer surface of the radial grid
|
||||
// Adjust the outer nodes to match the corner pillars of the host cell
|
||||
const double epsilon = 0.15;
|
||||
if ( fabs( maxRadius - cellRadius[opmNodeIndex] ) < epsilon * cellRadius[opmNodeIndex] )
|
||||
{
|
||||
const auto hostCellIndex = hostCellGlobalIndices[opmCellIndex];
|
||||
|
||||
double closestPillarDistance = std::numeric_limits<double>::max();
|
||||
int closestPillarIndex = -1;
|
||||
|
||||
const auto cylinderCoordX = opmX[opmNodeIndex] + xCenterCoordOpm;
|
||||
const auto cylinderCoordY = opmY[opmNodeIndex] + yCenterCoordOpm;
|
||||
const auto cylinderCoordZ = opmZ[opmNodeIndex];
|
||||
|
||||
const cvf::Vec3d coordinateOnCylinder = cvf::Vec3d( cylinderCoordX, cylinderCoordY, cylinderCoordZ );
|
||||
|
||||
const auto candidates = computeSnapToCoordinates( opmMainGrid, opmGrid, hostCellIndex, opmCellIndex );
|
||||
for ( int pillarIndex = 0; pillarIndex < static_cast<int>( candidates.size() ); pillarIndex++ )
|
||||
{
|
||||
for ( const auto& c : candidates[pillarIndex] )
|
||||
{
|
||||
double distance = coordinateOnCylinder.pointDistance( c );
|
||||
if ( distance < closestPillarDistance )
|
||||
{
|
||||
closestPillarDistance = distance;
|
||||
closestPillarIndex = pillarIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( closestPillarDistance < std::numeric_limits<double>::max() )
|
||||
{
|
||||
const auto& pillarCordinates = candidates[closestPillarIndex];
|
||||
|
||||
int layerCount = pillarCordinates.size() / 2;
|
||||
int layerIndexInMainGridCell = ijkCell[2] % layerCount;
|
||||
int localNodeIndex = opmNodeIndex % 8;
|
||||
|
||||
cvf::Vec3d closestPillarCoord;
|
||||
if ( localNodeIndex < 4 )
|
||||
{
|
||||
// Top of cell
|
||||
int pillarCoordIndex = layerIndexInMainGridCell * 2;
|
||||
closestPillarCoord = pillarCordinates[pillarCoordIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bottom of cell
|
||||
int pillarCoordIndex = layerIndexInMainGridCell * 2 + 1;
|
||||
closestPillarCoord = pillarCordinates[pillarCoordIndex];
|
||||
}
|
||||
|
||||
riNode.x() = closestPillarCoord.x();
|
||||
riNode.y() = closestPillarCoord.y();
|
||||
riNode.z() = -closestPillarCoord.z();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::map<int, std::pair<double, double>> RifOpmGridTools::computeXyCenterForTopOfCells( Opm::EclIO::EGrid& opmMainGrid,
|
||||
Opm::EclIO::EGrid& opmGrid,
|
||||
RigGridBase* riGrid )
|
||||
{
|
||||
if ( !riGrid || riGrid->isMainGrid() ) return {};
|
||||
|
||||
size_t cellCount = opmGrid.totalNumberOfCells();
|
||||
if ( cellCount != riGrid->cellCount() ) return {};
|
||||
|
||||
// Read out the corner coordinates from the EGRID file using radial coordinates.
|
||||
// Prefix OPM structures with _opm_and ResInsight structures with _ri_
|
||||
|
||||
// Compute the center of the LGR radial grid cells for each K layer
|
||||
std::map<int, std::pair<double, double>> radialGridCenterTopLayerOpm;
|
||||
|
||||
{
|
||||
std::array<double, 8> opmX{};
|
||||
std::array<double, 8> opmY{};
|
||||
std::array<double, 8> opmZ{};
|
||||
|
||||
std::map<int, std::vector<std::pair<double, double>>> xyCenterPerLayer;
|
||||
|
||||
auto hostCellGlobalIndices = opmGrid.hostCellsGlobalIndex();
|
||||
|
||||
for ( size_t cIdx = 0; cIdx < cellCount; cIdx++ )
|
||||
{
|
||||
auto mainGridCellIndex = hostCellGlobalIndices[cIdx];
|
||||
opmMainGrid.getCellCorners( mainGridCellIndex, opmX, opmY, opmZ );
|
||||
|
||||
auto ijkLocalGrid = opmGrid.ijk_from_global_index( cIdx );
|
||||
auto layer = ijkLocalGrid[2];
|
||||
|
||||
// Four corners for top
|
||||
for ( size_t i = 4; i < 8; i++ )
|
||||
{
|
||||
auto& xyCoords = xyCenterPerLayer[layer];
|
||||
xyCoords.emplace_back( opmX[i], opmY[i] );
|
||||
}
|
||||
}
|
||||
|
||||
for ( const auto& [k, xyCoords] : xyCenterPerLayer )
|
||||
{
|
||||
RiaWeightedMeanCalculator<double> xCoord;
|
||||
RiaWeightedMeanCalculator<double> yCoord;
|
||||
|
||||
for ( const auto& [x, y] : xyCoords )
|
||||
{
|
||||
xCoord.addValueAndWeight( x, 1.0 );
|
||||
yCoord.addValueAndWeight( y, 1.0 );
|
||||
}
|
||||
|
||||
radialGridCenterTopLayerOpm[k] = { xCoord.weightedMean(), yCoord.weightedMean() };
|
||||
}
|
||||
}
|
||||
|
||||
return radialGridCenterTopLayerOpm;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<cvf::Vec3d>> RifOpmGridTools::computeSnapToCoordinates( Opm::EclIO::EGrid& opmMainGrid,
|
||||
Opm::EclIO::EGrid& opmGrid,
|
||||
int mainGridCellIndex,
|
||||
int lgrCellIndex )
|
||||
{
|
||||
auto hostCellIndices = opmGrid.hostCellsGlobalIndex();
|
||||
auto lgrIjk = opmGrid.ijk_from_global_index( lgrCellIndex );
|
||||
|
||||
std::vector<double> zDistanceAlongPillar;
|
||||
|
||||
for ( int gridCellIndex = 0; gridCellIndex < opmGrid.totalNumberOfCells(); gridCellIndex++ )
|
||||
{
|
||||
if ( hostCellIndices[gridCellIndex] == mainGridCellIndex )
|
||||
{
|
||||
auto ijk = opmGrid.ijk_from_global_index( gridCellIndex );
|
||||
|
||||
// Find all LGR cells for the same IJ column
|
||||
if ( ijk[0] == lgrIjk[0] && ijk[1] == lgrIjk[1] )
|
||||
{
|
||||
std::array<double, 8> cellX{};
|
||||
std::array<double, 8> cellY{};
|
||||
std::array<double, 8> cellZ{};
|
||||
|
||||
opmGrid.getCellCorners( gridCellIndex, cellX, cellY, cellZ );
|
||||
|
||||
// Get top and bottom of one pillar
|
||||
zDistanceAlongPillar.push_back( cellZ[0] );
|
||||
zDistanceAlongPillar.push_back( cellZ[4] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( zDistanceAlongPillar.size() < 2 ) return {};
|
||||
|
||||
std::sort( zDistanceAlongPillar.begin(), zDistanceAlongPillar.end() );
|
||||
|
||||
auto normalize = []( const std::vector<double>& values ) -> std::vector<double> {
|
||||
if ( values.size() < 2 ) return {};
|
||||
|
||||
std::vector<double> normalizedValues;
|
||||
|
||||
double firstValue = values.front();
|
||||
double lastValue = values.back();
|
||||
double range = lastValue - firstValue;
|
||||
|
||||
// Normalize values to range [0..1]
|
||||
for ( const auto& value : values )
|
||||
{
|
||||
normalizedValues.emplace_back( ( value - firstValue ) / range );
|
||||
}
|
||||
|
||||
return normalizedValues;
|
||||
};
|
||||
|
||||
auto normalizedZValues = normalize( zDistanceAlongPillar );
|
||||
|
||||
std::vector<std::vector<cvf::Vec3d>> allCoords;
|
||||
std::array<double, 8> hostCellX{};
|
||||
std::array<double, 8> hostCellY{};
|
||||
std::array<double, 8> hostCellZ{};
|
||||
|
||||
opmMainGrid.getCellCorners( mainGridCellIndex, hostCellX, hostCellY, hostCellZ );
|
||||
|
||||
for ( int pillarIndex = 0; pillarIndex < 4; pillarIndex++ )
|
||||
{
|
||||
std::vector<cvf::Vec3d> pillarCoords;
|
||||
|
||||
const cvf::Vec3d p1( hostCellX[0 + pillarIndex], hostCellY[0 + pillarIndex], hostCellZ[0 + pillarIndex] );
|
||||
const cvf::Vec3d p2( hostCellX[4 + pillarIndex], hostCellY[4 + pillarIndex], hostCellZ[4 + pillarIndex] );
|
||||
|
||||
for ( auto t : normalizedZValues )
|
||||
{
|
||||
cvf::Vec3d pillarCoord = p1 * ( 1.0 - t ) + t * p2;
|
||||
pillarCoords.push_back( pillarCoord );
|
||||
}
|
||||
|
||||
allCoords.push_back( pillarCoords );
|
||||
}
|
||||
|
||||
return allCoords;
|
||||
}
|
60
ApplicationLibCode/FileInterface/RifOpmGridTools.h
Normal file
60
ApplicationLibCode/FileInterface/RifOpmGridTools.h
Normal file
@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023- 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
|
||||
|
||||
#include "cvfVector3.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
namespace EclIO
|
||||
{
|
||||
class EGrid;
|
||||
}
|
||||
} // namespace Opm
|
||||
|
||||
class RigMainGrid;
|
||||
class RigGridBase;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RifOpmGridTools
|
||||
{
|
||||
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 );
|
||||
|
||||
private:
|
||||
static void transferCoordinates( Opm::EclIO::EGrid& opmMainGrid,
|
||||
Opm::EclIO::EGrid& opmGrid,
|
||||
RigMainGrid* riMainGrid,
|
||||
RigGridBase* riGrid );
|
||||
|
||||
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 );
|
||||
};
|
@ -29,6 +29,7 @@
|
||||
#include "RifEclipseInputFileTools.h"
|
||||
#include "RifEclipseOutputFileTools.h"
|
||||
#include "RifHdf5ReaderInterface.h"
|
||||
#include "RifOpmGridTools.h"
|
||||
#include "RifReaderSettings.h"
|
||||
|
||||
#ifdef USE_HDF5
|
||||
@ -414,6 +415,8 @@ bool RifReaderEclipseOutput::open( const QString& fileName, RigEclipseCaseData*
|
||||
{
|
||||
auto task = progress.task( "Transferring grid geometry", 10 );
|
||||
if ( !transferGeometry( mainEclGrid, eclipseCase ) ) return false;
|
||||
|
||||
RifOpmGridTools::importCoordinatesForRadialGrid( fileName.toStdString(), eclipseCase->mainGrid() );
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -76,14 +76,7 @@ public:
|
||||
std::vector<QDateTime> allTimeSteps() const;
|
||||
|
||||
static bool transferGeometry( const ecl_grid_type* mainEclGrid, RigEclipseCaseData* eclipseCase );
|
||||
static bool exportGrid( const QString& gridFileName,
|
||||
RigEclipseCaseData* eclipseCase,
|
||||
const cvf::Vec3st& min,
|
||||
const cvf::Vec3st& max,
|
||||
const cvf::Vec3st& refinement );
|
||||
|
||||
static void transferCoarseningInfo( const ecl_grid_type* eclGrid, RigGridBase* grid );
|
||||
|
||||
static void importEquilData( const QString& deckFileName,
|
||||
const QString& includeStatementAbsolutePathPrefix,
|
||||
RigEclipseCaseData* eclipseCase );
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseView.h"
|
||||
|
||||
#include "cafPdmUiCheckBoxEditor.h"
|
||||
#include "cafPdmUiTreeSelectionEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimMultipleEclipseResults, "RimMultipleEclipseResults" );
|
||||
@ -32,9 +33,14 @@ RimMultipleEclipseResults::RimMultipleEclipseResults()
|
||||
{
|
||||
CAF_PDM_InitObject( "Multiple Result Info", ":/TextAnnotation16x16.png" );
|
||||
|
||||
CAF_PDM_InitField( &m_showCenterCoordinates, "showCenterCoordinates", false, "Show Center Coordinates" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_showCenterCoordinates );
|
||||
|
||||
CAF_PDM_InitField( &m_showCornerCoordinates, "showCornerCoordinates", false, "Show Corner Coordinates" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_showCornerCoordinates );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_selectedKeywords, "SelectedProperties", "Properties" );
|
||||
m_selectedKeywords.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
|
||||
|
||||
m_selectedKeywords.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
|
||||
}
|
||||
|
||||
@ -74,6 +80,22 @@ std::vector<RigEclipseResultAddress> RimMultipleEclipseResults::additionalResult
|
||||
return resultAddresses;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimMultipleEclipseResults::showCenterCoordinates() const
|
||||
{
|
||||
return m_showCenterCoordinates;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimMultipleEclipseResults::showCornerCoordinates() const
|
||||
{
|
||||
return m_showCornerCoordinates;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -40,10 +40,16 @@ public:
|
||||
|
||||
std::vector<RigEclipseResultAddress> additionalResultAddresses() const;
|
||||
|
||||
bool showCenterCoordinates() const;
|
||||
bool showCornerCoordinates() const;
|
||||
|
||||
private:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_showCornerCoordinates;
|
||||
caf::PdmField<bool> m_showCenterCoordinates;
|
||||
|
||||
caf::PdmField<std::vector<QString>> m_selectedKeywords;
|
||||
caf::PdmPointer<RimEclipseView> m_eclipseView;
|
||||
};
|
||||
|
@ -10,6 +10,7 @@
|
||||
// Disable warning from external library to make sure treat warnings as error works
|
||||
#pragma warning( disable : 4267 )
|
||||
#endif
|
||||
#include "opm/io/eclipse/EGrid.hpp"
|
||||
#include "opm/io/eclipse/ERft.hpp"
|
||||
#include "opm/io/eclipse/ESmry.hpp"
|
||||
#include "opm/io/eclipse/ExtESmry.hpp"
|
||||
@ -293,3 +294,33 @@ TEST( OpmSummaryTests, OpmComputeSegmentTopology )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( OpmSummaryTests, DISABLED_ReadOpmRadialGrid )
|
||||
{
|
||||
{
|
||||
QString filePath = "e:/models/from_equinor_sftp/2021.10.1-Radial-testcase/global-radial/GLOBAL-RADIAL.EGRID";
|
||||
|
||||
Opm::EclIO::EGrid eGrid( filePath.toStdString() );
|
||||
|
||||
auto dims = eGrid.dimension();
|
||||
|
||||
size_t cellCount = dims[0] * dims[1] * dims[2];
|
||||
|
||||
std::array<double, 8> X{};
|
||||
std::array<double, 8> Y{};
|
||||
std::array<double, 8> Z{};
|
||||
|
||||
for ( size_t cidx = 0; cidx < cellCount; cidx++ )
|
||||
{
|
||||
eGrid.getCellCorners( cidx, X, Y, Z );
|
||||
|
||||
for ( size_t i = 0; i < 8; i++ )
|
||||
{
|
||||
std::cout << X[i] << " " << Y[i] << " " << Z[i] << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "RimExtrudedCurveIntersection.h"
|
||||
#include "RimFormationNames.h"
|
||||
#include "RimIntersectionResultDefinition.h"
|
||||
#include "RimMultipleEclipseResults.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimReservoirCellResultsStorage.h"
|
||||
#include "RimViewLinker.h"
|
||||
@ -195,7 +196,7 @@ QString RiuResultTextBuilder::mainResultText()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiuResultTextBuilder::geometrySelectionText( QString itemSeparator )
|
||||
QString RiuResultTextBuilder::geometrySelectionText( const QString& itemSeparator )
|
||||
{
|
||||
QString text;
|
||||
|
||||
@ -234,6 +235,8 @@ QString RiuResultTextBuilder::geometrySelectionText( QString itemSeparator )
|
||||
|
||||
size_t globalCellIndex = grid->reservoirCellIndex( m_cellIndex );
|
||||
text += QString( "Global Cell Index : %4" ).arg( globalCellIndex ) + itemSeparator;
|
||||
|
||||
text += coordinatesText( grid, globalCellIndex, itemSeparator );
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,10 +254,8 @@ QString RiuResultTextBuilder::geometrySelectionText( QString itemSeparator )
|
||||
if ( !t.isZero() )
|
||||
{
|
||||
cvf::Vec3d intPt = m_intersectionPointInDisplay.getTransformedPoint( t );
|
||||
formattedText = QString( "Intersection point : [E: %1, N: %2, Depth: %3]" )
|
||||
.arg( intPt.x(), 5, 'f', 2 )
|
||||
.arg( intPt.y(), 5, 'f', 2 )
|
||||
.arg( -intPt.z(), 5, 'f', 2 );
|
||||
formattedText =
|
||||
createTextFromDomainCoordinate( "Intersection point : [E: %1, N: %2, Depth: %3]", intPt );
|
||||
text += formattedText;
|
||||
}
|
||||
}
|
||||
@ -265,10 +266,8 @@ QString RiuResultTextBuilder::geometrySelectionText( QString itemSeparator )
|
||||
cvf::ref<caf::DisplayCoordTransform> transForm = m_displayCoordView->displayCoordTransform();
|
||||
cvf::Vec3d domainCoord = transForm->translateToDomainCoord( m_intersectionPointInDisplay );
|
||||
|
||||
formattedText = QString( "Intersection point : [E: %1, N: %2, Depth: %3]" )
|
||||
.arg( domainCoord.x(), 5, 'f', 2 )
|
||||
.arg( domainCoord.y(), 5, 'f', 2 )
|
||||
.arg( -domainCoord.z(), 5, 'f', 2 );
|
||||
formattedText =
|
||||
createTextFromDomainCoordinate( "Intersection point : [E: %1, N: %2, Depth: %3]", domainCoord );
|
||||
text += formattedText;
|
||||
}
|
||||
}
|
||||
@ -279,6 +278,74 @@ QString RiuResultTextBuilder::geometrySelectionText( QString itemSeparator )
|
||||
return text;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiuResultTextBuilder::coordinatesText( const RigGridBase* grid, size_t globalCellIndex, const QString& itemSeparator )
|
||||
{
|
||||
QString text;
|
||||
|
||||
bool showCenter = false;
|
||||
bool showCorner = false;
|
||||
|
||||
if ( m_eclipseView )
|
||||
{
|
||||
std::vector<RimMultipleEclipseResults*> additionalResultSettings;
|
||||
m_eclipseView->descendantsOfType( additionalResultSettings );
|
||||
if ( !additionalResultSettings.empty() )
|
||||
{
|
||||
showCenter = additionalResultSettings[0]->showCenterCoordinates();
|
||||
showCorner = additionalResultSettings[0]->showCornerCoordinates();
|
||||
}
|
||||
}
|
||||
|
||||
if ( showCenter )
|
||||
{
|
||||
auto mainGrid = grid->mainGrid();
|
||||
auto cell = mainGrid->cell( globalCellIndex );
|
||||
const auto center = cell.center();
|
||||
|
||||
text += createTextFromDomainCoordinate( "Cell Center : [%1, %2, %3]", center ) + itemSeparator;
|
||||
}
|
||||
|
||||
if ( showCorner )
|
||||
{
|
||||
auto mainGrid = grid->mainGrid();
|
||||
auto cell = mainGrid->cell( globalCellIndex );
|
||||
auto indices = cell.cornerIndices();
|
||||
|
||||
text += QString( "Cell Corners" ) + itemSeparator;
|
||||
|
||||
const std::vector<std::pair<int, std::string>> riNodeOrder{ { 0, "i- j- k+" },
|
||||
{ 1, "i+ j- k+" },
|
||||
{ 2, "i+ j+ k+" },
|
||||
{ 3, "i- j+ k+" },
|
||||
{ 4, "i- j- k-" },
|
||||
{ 5, "i+ j- k-" },
|
||||
{ 6, "i+ j+ k-" },
|
||||
{ 7, "i- j+ k-" } };
|
||||
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
{
|
||||
const auto& [nodeIndex, nodeText] = riNodeOrder[i];
|
||||
auto v = mainGrid->nodes()[indices[nodeIndex]];
|
||||
|
||||
text += createTextFromDomainCoordinate( QString::fromStdString( nodeText ) + " : [%1, %2, %3]" + itemSeparator,
|
||||
v );
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiuResultTextBuilder::createTextFromDomainCoordinate( const QString& formatString, const cvf::Vec3d& domainCoord )
|
||||
{
|
||||
return formatString.arg( domainCoord.x(), 5, 'f', 2 ).arg( domainCoord.y(), 5, 'f', 2 ).arg( -domainCoord.z(), 5, 'f', 2 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
|
||||
#include "cvfStructGrid.h"
|
||||
|
||||
#include <map>
|
||||
@ -30,6 +31,7 @@ class Rim2dIntersectionView;
|
||||
class RigEclipseCaseData;
|
||||
class RimEclipseResultDefinition;
|
||||
class RimGridView;
|
||||
class RigGridBase;
|
||||
|
||||
class QString;
|
||||
|
||||
@ -62,7 +64,7 @@ public:
|
||||
|
||||
QString mainResultText();
|
||||
|
||||
QString geometrySelectionText( QString itemSeparator );
|
||||
QString geometrySelectionText( const QString& itemSeparator );
|
||||
|
||||
private:
|
||||
void appendDetails( QString& text, const QString& details );
|
||||
@ -90,6 +92,10 @@ private:
|
||||
|
||||
std::pair<bool, QStringList> resultTextFromLinkedViews() const;
|
||||
|
||||
QString coordinatesText( const RigGridBase* grid, size_t globalCellIndex, const QString& itemSeparator );
|
||||
|
||||
static QString createTextFromDomainCoordinate( const QString& formatString, const cvf::Vec3d& domainCoord );
|
||||
|
||||
private:
|
||||
caf::PdmPointer<RimGridView> m_displayCoordView;
|
||||
caf::PdmPointer<RimEclipseView> m_eclipseView;
|
||||
|
2
ThirdParty/custom-opm-common/opm-common
vendored
2
ThirdParty/custom-opm-common/opm-common
vendored
@ -1 +1 @@
|
||||
Subproject commit aa8e9c1f84a8ccfe829c3a89295c442e95bb2a09
|
||||
Subproject commit c548d4ea4319adee307bba5ddd8d68bb1f44d421
|
Loading…
Reference in New Issue
Block a user