Support filtering by formation/polygon when calculating statistics (#12086)

* Support loading formation names when importing an ensemble
* Enable support for formation filtering when calculating contour map
* Add option to limit calculation area to a selection of polygons
This commit is contained in:
jonjenssen
2025-01-29 01:36:29 +01:00
committed by GitHub
parent 99c4d96977
commit cbab1b256f
43 changed files with 460 additions and 86 deletions

View File

@@ -45,6 +45,7 @@
#include "RicfCommandFileExecutor.h"
#include "RicfCommandObject.h"
#include "Formations/RimFormationNamesCollection.h"
#include "PlotTemplates/RimPlotTemplateFolderItem.h"
#include "Polygons/RimPolygonCollection.h"
#include "QuickAccess/RimQuickAccessCollection.h"
@@ -60,7 +61,6 @@
#include "RimFaultReactivationModelCollection.h"
#include "RimFileWellPath.h"
#include "RimFileWellPathDataLoader.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechModels.h"

View File

@@ -47,6 +47,7 @@
#include "RicImportGeneralDataFeature.h"
#include "SummaryPlotCommands/RicSummaryPlotFeatureImpl.h"
#include "Formations/RimFormationNamesCollection.h"
#include "Rim2dIntersectionViewCollection.h"
#include "RimAnnotationCollection.h"
#include "RimAnnotationInViewCollection.h"
@@ -54,7 +55,6 @@
#include "RimEclipseCaseCollection.h"
#include "RimEclipseView.h"
#include "RimFlowPlotCollection.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechCellColors.h"

View File

@@ -109,6 +109,7 @@ list(
ProjectDataModel/Summary/CMakeLists_files.cmake
ProjectDataModel/Summary/Sumo/CMakeLists_files.cmake
ProjectDataModel/Flow/CMakeLists_files.cmake
ProjectDataModel/Formations/CMakeLists_files.cmake
ProjectDataModel/Annotations/CMakeLists_files.cmake
ProjectDataModel/Completions/CMakeLists_files.cmake
ProjectDataModel/Measurement/CMakeLists_files.cmake

View File

@@ -19,8 +19,8 @@
#include "RicImportFormationNamesFeature.h"
#include "Formations/RimFormationNames.h"
#include "RimCase.h"
#include "RimFormationNames.h"
#include "RimProject.h"
#include "cafPdmFieldScriptingCapability.h"

View File

@@ -20,11 +20,18 @@
#include "RiaApplication.h"
#include "RiaImportEclipseCaseTools.h"
#include "RiaLogging.h"
#include "RicCreateGridCaseGroupFromFilesFeature.h"
#include "RicImportFormationNamesFeature.h"
#include "RicNewViewFeature.h"
#include "RicRecursiveFileSearchDialog.h"
#include "RigFormationNames.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "Formations/RimFormationTools.h"
#include "Rim3dView.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseCaseEnsemble.h"
@@ -35,8 +42,10 @@
#include "cafProgressInfo.h"
#include "cafSelectionManager.h"
#include "cafUtils.h"
#include <QAction>
#include <QDir>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT( RicCreateGridCaseEnsemblesFromFilesFeature, "RicCreateGridCaseEnsemblesFromFilesFeature" );
@@ -115,9 +124,13 @@ RimEclipseCaseEnsemble* RicCreateGridCaseEnsemblesFromFilesFeature::importSingle
QString caseName = gridFileName.completeBaseName();
auto* rimResultReservoir = new RimEclipseResultCase();
rimResultReservoir->setCaseInfo( caseName, caseFileName );
eclipseCaseEnsemble->addCase( rimResultReservoir );
auto* rimResultCase = new RimEclipseResultCase();
rimResultCase->setCaseInfo( caseName, caseFileName );
eclipseCaseEnsemble->addCase( rimResultCase );
auto folderName = RimFormationTools::formationFolderFromCaseFileName( caseFileName );
RimFormationNames* formations = RimFormationTools::loadFormationNamesFromFolder( folderName );
if ( formations != nullptr ) rimResultCase->setFormationNames( formations );
}
oilfield->analysisModels()->caseEnsembles.push_back( eclipseCaseEnsemble );

View File

@@ -25,6 +25,7 @@
#include <vector>
class RimEclipseCaseEnsemble;
class RimFormationNames;
//==================================================================================================
///

View File

@@ -26,10 +26,10 @@
#include "RigElasticProperties.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "RigFormationNames.h"
#include "RimElasticProperties.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimStimPlanModelTemplate.h"

View File

@@ -26,6 +26,8 @@
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "Rim3dView.h"
#include "RimCase.h"
#include "RimColorLegend.h"
@@ -35,8 +37,6 @@
#include "RimEclipseCellColors.h"
#include "RimEclipseContourMapView.h"
#include "RimEclipseView.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechCellColors.h"
#include "RimGeoMechContourMapView.h"

View File

@@ -26,7 +26,7 @@
#include "RifReaderFmuRft.h"
#include "RimFormationNames.h"
#include "Formations/RimFormationNames.h"
#include "RimObservedDataCollection.h"
#include "RimObservedFmuRftData.h"
#include "RimObservedSummaryData.h"

View File

@@ -26,7 +26,7 @@
#include "RifReaderFmuRft.h"
#include "RimFormationNames.h"
#include "Formations/RimFormationNames.h"
#include "RimObservedDataCollection.h"
#include "RimObservedSummaryData.h"
#include "RimOilField.h"

View File

@@ -20,8 +20,8 @@
#include "RiaLogging.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "cafSelectionManager.h"

View File

@@ -31,8 +31,6 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEclipseStatisticsCaseEvaluator.h
${CMAKE_CURRENT_LIST_DIR}/RimMimeData.h
${CMAKE_CURRENT_LIST_DIR}/RimTools.h
${CMAKE_CURRENT_LIST_DIR}/RimFormationNames.h
${CMAKE_CURRENT_LIST_DIR}/RimFormationNamesCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimMockModelSettings.h
${CMAKE_CURRENT_LIST_DIR}/RimTernaryLegendConfig.h
${CMAKE_CURRENT_LIST_DIR}/RimEclipseFaultColors.h
@@ -172,8 +170,6 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimEclipseStatisticsCaseEvaluator.cpp
${CMAKE_CURRENT_LIST_DIR}/RimMimeData.cpp
${CMAKE_CURRENT_LIST_DIR}/RimTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFormationNames.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFormationNamesCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimMockModelSettings.cpp
${CMAKE_CURRENT_LIST_DIR}/RimTernaryLegendConfig.cpp
${CMAKE_CURRENT_LIST_DIR}/RimEclipseFaultColors.cpp

View File

@@ -0,0 +1,15 @@
set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimFormationNames.h
${CMAKE_CURRENT_LIST_DIR}/RimFormationNamesCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimFormationTools.h
)
set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimFormationNames.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFormationNamesCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimFormationTools.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})

View File

@@ -0,0 +1,63 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 - Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimFormationTools.h"
#include "RiaLogging.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "cafUtils.h"
#include <QDir>
#include <QFileInfo>
#include <QStringList>
//--------------------------------------------------------------------------------------------------
/// look for formation file two levels up from the egrid file
//--------------------------------------------------------------------------------------------------
QString RimFormationTools::formationFolderFromCaseFileName( const QString caseFileName )
{
QFileInfo fi( caseFileName );
auto formationFolder = QDir( fi.dir().path() + "/../../" );
return formationFolder.absolutePath();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimFormationNames* RimFormationTools::loadFormationNamesFromFolder( const QString folderName )
{
QStringList filters;
filters << "*.lyr";
QStringList fileList = caf::Utils::getFilesInDirectory( folderName, filters, true /*absolute filename*/ );
if ( fileList.isEmpty() ) return nullptr;
RimFormationNamesCollection* fomNameColl = new RimFormationNamesCollection();
std::vector<RimFormationNames*> formationNames = fomNameColl->importFiles( fileList );
if ( formationNames.size() > 1 )
{
RiaLogging::warning( QString( "Multiple formation name files found in ensemble folder %1" ).arg( folderName ) );
}
return formationNames.back();
}

View File

@@ -0,0 +1,32 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 - Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QString>
class RimFormationNames;
class RimFormationTools
{
public:
static QString formationFolderFromCaseFileName( const QString caseFileName );
static RimFormationNames* loadFormationNamesFromFolder( const QString folderName );
private:
RimFormationTools(){};
};

View File

@@ -34,9 +34,9 @@
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "Formations/RimFormationNames.h"
#include "Rim2dIntersectionViewCollection.h"
#include "RimCellFilterCollection.h"
#include "RimFormationNames.h"
#include "RimGeoMechCellColors.h"
#include "RimGeoMechContourMapView.h"
#include "RimGeoMechContourMapViewCollection.h"

View File

@@ -39,13 +39,13 @@
#include "RiuPlotWidget.h"
#include "RiuScalarMapperLegendFrame.h"
#include "Formations/RimFormationNames.h"
#include "RimCase.h"
#include "RimEclipseCase.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseResultDefinition.h"
#include "RimEclipseView.h"
#include "RimFormationNames.h"
#include "RimGridCrossPlot.h"
#include "RimGridCrossPlotCurve.h"
#include "RimGridCrossPlotRegressionCurve.h"

View File

@@ -21,8 +21,8 @@
#include "RicfCommandObject.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimTimeStepFilter.h"

View File

@@ -21,6 +21,8 @@
#include "RiaApplication.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "PlotTemplates/RimPlotTemplateFileItem.h"
#include "PlotTemplates/RimPlotTemplateFolderItem.h"
#include "Rim3dOverlayInfoConfig.h"
@@ -69,8 +71,6 @@
#include "RimFlowCharacteristicsPlot.h"
#include "RimFlowDiagSolution.h"
#include "RimFlowPlotCollection.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechCellColors.h"

View File

@@ -121,7 +121,7 @@ void RimContourMapProjection::generateResultsIfNecessary( int timeStep )
if ( gridMappingNeedsUpdating() )
{
m_contourMapProjection->setCellVisibility( getCellVisibility() );
m_contourMapProjection->generateGridMapping( m_resultAggregation(), retrieveParameterWeights() );
m_contourMapProjection->generateGridMapping( m_resultAggregation(), retrieveParameterWeights(), m_selectedKLayers, {} );
}
progress.setProgress( 20 );
m_mapCellVisibility = m_contourMapProjection->getMapCellVisibility( timeStep, m_resultAggregation() );
@@ -648,3 +648,11 @@ void RimContourMapProjection::clearMinMaxValueRange()
m_minResultAllTimeSteps = std::numeric_limits<double>::infinity();
m_maxResultAllTimeSteps = -std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimContourMapProjection::useKLayers( std::set<int> kLayers )
{
m_selectedKLayers = kLayers;
}

View File

@@ -30,6 +30,8 @@
#include "cvfArray.h"
#include "cvfVector2.h"
#include <set>
class RigContourMapGrid;
class RimGridView;
class RimRegularLegendConfig;
@@ -64,6 +66,9 @@ public:
bool showContourLines() const;
bool showContourLabels() const;
// k layer filter, only consider kLayers in the given set (0-based index)
void useKLayers( std::set<int> kLayers );
virtual QString resultAggregationText() const;
QString caseName() const;
@@ -154,6 +159,8 @@ protected:
caf::PdmField<double> m_upperThreshold;
caf::PdmField<double> m_lowerThreshold;
std::set<int> m_selectedKLayers;
std::unique_ptr<RigContourMapGrid> m_contourMapGrid;
std::unique_ptr<RigContourMapProjection> m_contourMapProjection;

View File

@@ -43,6 +43,7 @@
#include "Well/RigSimWellData.h"
#include "Well/RigWellResultFrame.h"
#include "Formations/RimFormationNames.h"
#include "Rim2dIntersectionViewCollection.h"
#include "RimCaseCollection.h"
#include "RimCellEdgeColors.h"
@@ -59,7 +60,6 @@
#include "RimEclipseView.h"
#include "RimEclipseViewCollection.h"
#include "RimFaultInViewCollection.h"
#include "RimFormationNames.h"
#include "RimGridCollection.h"
#include "RimIntersectionCollection.h"
#include "RimMainPlotCollection.h"

View File

@@ -44,7 +44,10 @@
#include "RigFlowDiagSolverInterface.h"
#include "RigMainGrid.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationTools.h"
#include "RimDialogData.h"
#include "RimEclipseCaseEnsemble.h"
#include "RimEclipseCellColors.h"
#include "RimEclipseInputProperty.h"
#include "RimEclipseInputPropertyCollection.h"
@@ -110,6 +113,21 @@ bool RimEclipseResultCase::openEclipseGridFile()
return importGridAndResultMetaData( false );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseResultCase::initAfterRead()
{
RimEclipseCase::initAfterRead();
// handle special formations for ensembles
if ( firstAncestorOrThisOfType<RimEclipseCaseEnsemble>() != nullptr )
{
auto folderName = RimFormationTools::formationFolderFromCaseFileName( m_caseFileName().path() );
m_activeFormationNames = RimFormationTools::loadFormationNamesFromFolder( folderName );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -695,3 +713,30 @@ void RimEclipseResultCase::defineEditorAttribute( const caf::PdmFieldHandle* fie
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimEclipseResultCase::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
// if this is part of an ensemble, use lyr file set during ensemble creating
if ( fieldNeedingOptions == &m_activeFormationNames )
{
auto ensemble = firstAncestorOrThisOfType<RimEclipseCaseEnsemble>();
if ( ensemble != nullptr )
{
QList<caf::PdmOptionItemInfo> options;
if ( m_activeFormationNames() )
{
options.push_back( caf::PdmOptionItemInfo( m_activeFormationNames->fileNameWoPath(), m_activeFormationNames(), false ) );
}
else
{
options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) );
}
return options;
}
}
return RimEclipseCase::calculateValueOptions( fieldNeedingOptions );
}

View File

@@ -80,6 +80,8 @@ public:
protected:
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
void initAfterRead() override;
private:
void loadAndUpdateSourSimData();

View File

@@ -20,13 +20,13 @@
#include "RimOilField.h"
#include "Formations/RimFormationNamesCollection.h"
#include "RimAnnotationCollection.h"
#include "RimCompletionTemplateCollection.h"
#include "RimEclipseCaseCollection.h"
#include "RimEclipseContourMapViewCollection.h"
#include "RimEclipseViewCollection.h"
#include "RimEnsembleWellLogsCollection.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechModels.h"
#include "RimMeasurement.h"

View File

@@ -35,6 +35,7 @@
#include "RigGridBase.h"
#include "Cloud/RimCloudDataSourceCollection.h"
#include "Formations/RimFormationNamesCollection.h"
#include "PlotTemplates/RimPlotTemplateFolderItem.h"
#include "Polygons/RimPolygonCollection.h"
#include "QuickAccess/RimQuickAccessCollection.h"
@@ -59,7 +60,6 @@
#include "RimEnsembleWellLogsCollection.h"
#include "RimFileWellPath.h"
#include "RimFlowPlotCollection.h"
#include "RimFormationNamesCollection.h"
#include "RimFractureTemplate.h"
#include "RimFractureTemplateCollection.h"
#include "RimGeoMechCase.h"

View File

@@ -32,13 +32,19 @@
#include "RigEclipseCaseData.h"
#include "RigEclipseContourMapProjection.h"
#include "RigEclipseResultAddress.h"
#include "RigFormationNames.h"
#include "RigMainGrid.h"
#include "RigPolyLinesData.h"
#include "RigStatisticsMath.h"
#include "Formations/RimFormationNames.h"
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonCollection.h"
#include "RimEclipseCase.h"
#include "RimEclipseCaseEnsemble.h"
#include "RimEclipseContourMapProjection.h"
#include "RimEclipseResultDefinition.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSimWellInViewCollection.h"
#include "RimStatisticsContourMapProjection.h"
@@ -54,6 +60,7 @@
#include "cafProgressInfo.h"
#include <limits>
#include <set>
CAF_PDM_SOURCE_INIT( RimStatisticsContourMap, "RimStatisticalContourMap" );
@@ -115,6 +122,14 @@ RimStatisticsContourMap::RimStatisticsContourMap()
CAF_PDM_InitFieldNoDefault( &m_views, "ContourMapViews", "Contour Maps", ":/CrossSection16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_selectedFormations, "Formations", "Select Formations" );
m_selectedFormations.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_selectedFormations.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
CAF_PDM_InitFieldNoDefault( &m_selectedPolygons, "Polygons", "Select Polygons" );
m_selectedPolygons.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_selectedPolygons.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::TOP );
setDeletable( true );
}
@@ -131,6 +146,7 @@ void RimStatisticsContourMap::defineUiOrdering( QString uiConfigName, caf::PdmUi
}
uiOrdering.add( nameField() );
uiOrdering.add( &m_computeStatisticsButton );
auto genGrp = uiOrdering.addNewGroup( "General" );
@@ -143,13 +159,31 @@ void RimStatisticsContourMap::defineUiOrdering( QString uiConfigName, caf::PdmUi
tsGroup->setCollapsedByDefault();
tsGroup->add( &m_selectedTimeSteps );
if ( eclipseCase() && eclipseCase()->activeFormationNames() )
{
auto formationGrp = uiOrdering.addNewGroup( "Formation Selection" );
formationGrp->setCollapsedByDefault();
formationGrp->add( &m_selectedFormations );
}
RimProject* proj = RimProject::current();
if ( auto polygonCollection = proj->activeOilField()->polygonCollection().p() )
{
if ( !polygonCollection->allPolygons().empty() )
{
auto polyGrp = uiOrdering.addNewGroup( "Polygon Selection" );
polyGrp->setCollapsedByDefault();
polyGrp->add( &m_selectedPolygons );
}
}
if ( !isColumnResult() )
{
auto resultDefinitionGroup = uiOrdering.addNewGroup( "Result Definition" );
m_resultDefinition->uiOrdering( uiConfigName, *resultDefinitionGroup );
}
uiOrdering.add( &m_computeStatisticsButton );
uiOrdering.skipRemainingFields();
}
//--------------------------------------------------------------------------------------------------
@@ -278,6 +312,33 @@ QList<caf::PdmOptionItemInfo> RimStatisticsContourMap::calculateValueOptions( co
}
return options;
}
else if ( &m_selectedFormations == fieldNeedingOptions )
{
if ( auto eCase = eclipseCase() )
{
if ( auto formations = eCase->activeFormationNames() )
{
if ( formations->formationNamesData() )
{
for ( auto f : formations->formationNamesData()->formationNames() )
{
options.push_back( caf::PdmOptionItemInfo( f, f, false ) );
}
}
}
}
}
else if ( &m_selectedPolygons == fieldNeedingOptions )
{
RimProject* proj = RimProject::current();
if ( auto polygonCollection = proj->activeOilField()->polygonCollection().p() )
{
for ( auto p : polygonCollection->allPolygons() )
{
options.push_back( caf::PdmOptionItemInfo( p->name(), p, false ) );
}
}
}
return options;
}
@@ -407,12 +468,6 @@ void RimStatisticsContourMap::computeStatistics()
auto contourMapGrid = std::make_unique<RigContourMapGrid>( gridBoundingBox, sampleSpacing );
auto firstEclipseCaseData = eclipseCase()->eclipseCaseData();
auto firstResultData = firstEclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
RigEclipseContourMapProjection contourMapProjection( *contourMapGrid, *firstEclipseCaseData, *firstResultData );
m_gridMapping = contourMapProjection.generateGridMapping( resultAggregation, {} );
const size_t nCases = ensemble->cases().size();
std::map<size_t, std::vector<std::vector<double>>> timestep_results;
@@ -432,13 +487,22 @@ void RimStatisticsContourMap::computeStatistics()
if ( eCase->ensureReservoirCaseIsOpen() )
{
RiaLogging::info( QString( "Grid: %1" ).arg( eCase->caseUserDescription() ) );
RiaLogging::info( QString( "Processing Grid: %1" ).arg( eCase->caseUserDescription() ) );
auto eclipseCaseData = eCase->eclipseCaseData();
auto resultData = eclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
RigEclipseContourMapProjection contourMapProjection( *contourMapGrid, *eclipseCaseData, *resultData );
contourMapProjection.generateGridMapping( resultAggregation, {} );
std::set<int> usedKLayers;
auto formationNames = selectedFormations();
if ( formationNames.size() > 0 )
{
usedKLayers = eCase->activeFormationNames()->formationNamesData()->findKLayers( formationNames );
}
contourMapProjection.generateGridMapping( resultAggregation, {}, usedKLayers, selectedPolygons() );
if ( m_resultDefinition()->hasDynamicResult() )
{
@@ -535,6 +599,36 @@ std::vector<int> RimStatisticsContourMap::selectedTimeSteps() const
return steps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimStatisticsContourMap::selectedFormations() const
{
return m_selectedFormations();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<cvf::Vec3d>> RimStatisticsContourMap::selectedPolygons()
{
std::vector<std::vector<cvf::Vec3d>> allLines;
for ( auto p : m_selectedPolygons() )
{
auto pData = p->polyLinesData();
if ( pData.isNull() ) continue;
const std::vector<std::vector<cvf::Vec3d>> lines = pData->completePolyLines();
for ( auto l : lines )
{
allLines.push_back( l );
}
}
return allLines;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -19,12 +19,17 @@
#pragma once
#include "RimNamedObject.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "ContourMap/RimContourMapResolutionTools.h"
#include "RimContourMapProjection.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
#include "cafPdmPtrArrayField.h"
#include "cafPdmPtrField.h"
#include "cvfVector3.h"
#include <map>
class RimEclipseCase;
@@ -32,6 +37,8 @@ class RimEclipseResultDefinition;
class RimEclipseCaseEnsemble;
class RimEclipseContourMapView;
class RimStatisticsContourMapView;
class RimPolygon;
class RigPolyLinesData;
//==================================================================================================
//
@@ -76,6 +83,9 @@ public:
std::vector<int> selectedTimeSteps() const;
QString timeStepName( int timeStep ) const;
std::vector<QString> selectedFormations() const;
std::vector<std::vector<cvf::Vec3d>> selectedPolygons();
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
@@ -95,15 +105,14 @@ private:
caf::PdmField<std::vector<int>> m_selectedTimeSteps;
caf::PdmChildField<RimEclipseResultDefinition*> m_resultDefinition;
caf::PdmField<bool> m_computeStatisticsButton;
caf::PdmField<std::vector<QString>> m_selectedFormations;
caf::PdmField<QString> m_primaryCase;
caf::PdmPtrArrayField<RimPolygon*> m_selectedPolygons;
caf::PdmField<caf::AppEnum<RimContourMapResolutionTools::SamplingResolution>> m_resolution;
std::unique_ptr<RigContourMapGrid> m_contourMapGrid;
std::map<size_t, std::map<StatisticsType, std::vector<double>>> m_timeResults;
std::vector<std::vector<std::pair<size_t, double>>> m_gridMapping;
caf::PdmChildArrayField<RimStatisticsContourMapView*> m_views;
};

View File

@@ -23,6 +23,8 @@
#include "RiaOptionItemFactory.h"
#include "RiaResultNames.h"
#include "Formations/RimFormationNames.h"
#include "Formations/RimFormationNamesCollection.h"
#include "RimEnsembleCurveFilter.h"
#include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSet.h"
@@ -31,8 +33,6 @@
#include "RimEnsembleWellLogStatisticsCurve.h"
#include "RimEnsembleWellLogs.h"
#include "RimEnsembleWellLogsCollection.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
#include "RimProject.h"

View File

@@ -24,7 +24,9 @@
#include "RigContourMapGrid.h"
#include "RigCellGeometryTools.h"
#include "RigContourMapProjection.h"
#include "RigPolyLinesData.h"
#include <algorithm>
#include <cmath>
@@ -221,6 +223,26 @@ double RigContourMapCalculator::calculateSum( const RigContourMapProjection&
return sum;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RigContourMapCalculator::isPointInsidePolygons( cvf::Vec2d point, const std::vector<std::vector<cvf::Vec3d>>& polygons )
{
cvf::Vec3d pos3D( point );
bool bIncludesCell = false;
for ( auto p : polygons )
{
if ( !bIncludesCell && RigCellGeometryTools::pointInsidePolygon2D( pos3D, p ) )
{
bIncludesCell = true;
}
}
return bIncludesCell;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -228,36 +250,43 @@ std::vector<std::vector<std::pair<size_t, double>>>
RigContourMapCalculator::generateGridMapping( RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
ResultAggregationType resultAggregation,
const std::vector<double>& weightingResultValues )
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons )
{
int nCells = contourMapGrid.numberOfCells();
std::vector<std::vector<std::pair<size_t, double>>> projected3dGridIndices( nCells );
if ( RigContourMapCalculator::isStraightSummationResult( resultAggregation ) )
{
const bool isSummationResult = RigContourMapCalculator::isStraightSummationResult( resultAggregation );
const bool usePolygonLimits = limitToPolygons.size() > 0;
#pragma omp parallel for
for ( int index = 0; index < nCells; ++index )
{
cvf::Vec2ui ij = contourMapGrid.ijFromCellIndex( index );
cvf::Vec2d globalPos = contourMapGrid.cellCenterPosition( ij.x(), ij.y() ) + contourMapGrid.origin2d();
projected3dGridIndices[index] =
cellRayIntersectionAndResults( contourMapProjection, contourMapGrid, globalPos, weightingResultValues );
if ( usePolygonLimits )
{
if ( !isPointInsidePolygons( globalPos, limitToPolygons ) )
{
projected3dGridIndices[index] = {};
continue;
}
}
if ( isSummationResult )
{
projected3dGridIndices[index] =
cellRayIntersectionAndResults( contourMapProjection, contourMapGrid, globalPos, weightingResultValues, kLayers );
}
else
{
#pragma omp parallel for
for ( int index = 0; index < nCells; ++index )
{
cvf::Vec2ui ij = contourMapGrid.ijFromCellIndex( index );
cvf::Vec2d globalPos = contourMapGrid.cellCenterPosition( ij.x(), ij.y() ) + contourMapGrid.origin2d();
projected3dGridIndices[index] =
cellOverlapVolumesAndResults( contourMapProjection, contourMapGrid, globalPos, weightingResultValues );
cellOverlapVolumesAndResults( contourMapProjection, contourMapGrid, globalPos, weightingResultValues, kLayers );
}
}
return projected3dGridIndices;
}
@@ -268,7 +297,8 @@ std::vector<RigContourMapCalculator::CellIndexAndResult>
RigContourMapCalculator::cellOverlapVolumesAndResults( const RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
const cvf::Vec2d& globalPos2d,
const std::vector<double>& weightingResultValues )
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers )
{
const cvf::BoundingBox& expandedBoundingBox = contourMapGrid.expandedBoundingBox();
cvf::Vec3d top2dElementCentroid( globalPos2d, expandedBoundingBox.max().z() );
@@ -302,6 +332,11 @@ std::vector<RigContourMapCalculator::CellIndexAndResult>
{
if ( cellGridIdxVisibility.isNull() || ( *cellGridIdxVisibility )[globalCellIdx] )
{
auto k = contourMapProjection.kLayer( globalCellIdx );
if ( !kLayers.empty() )
{
if ( !kLayers.contains( (int)k ) ) continue;
}
kLayerCellIndexVector[contourMapProjection.kLayer( globalCellIdx )].push_back( globalCellIdx );
}
}
@@ -334,7 +369,8 @@ std::vector<RigContourMapCalculator::CellIndexAndResult>
RigContourMapCalculator::cellRayIntersectionAndResults( const RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
const cvf::Vec2d& globalPos2d,
const std::vector<double>& weightingResultValues )
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers )
{
std::vector<std::pair<size_t, double>> matchingVisibleCellsAndWeight;
@@ -362,7 +398,12 @@ std::vector<RigContourMapCalculator::CellIndexAndResult>
{
if ( cellGridIdxVisibility.isNull() || ( *cellGridIdxVisibility )[globalCellIdx] )
{
kLayerIndexMap[contourMapProjection.kLayer( globalCellIdx )].push_back( globalCellIdx );
auto k = contourMapProjection.kLayer( globalCellIdx );
if ( !kLayers.empty() )
{
if ( !kLayers.contains( (int)k ) ) continue;
}
kLayerIndexMap[k].push_back( globalCellIdx );
}
}

View File

@@ -19,12 +19,15 @@
#pragma once
#include "cvfVector2.h"
#include "cvfVector3.h"
#include <set>
#include <utility>
#include <vector>
class RigContourMapGrid;
class RigContourMapProjection;
class RigPolyLinesData;
//==================================================================================================
///
@@ -50,10 +53,13 @@ public:
HYDROCARBON_COLUMN
};
static std::vector<std::vector<std::pair<size_t, double>>> generateGridMapping( RigContourMapProjection& contourMapProjection,
static std::vector<std::vector<std::pair<size_t, double>>>
generateGridMapping( RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
ResultAggregationType resultAggregation,
const std::vector<double>& weightingResultValues );
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons );
static double calculateValueInMapCell( const RigContourMapProjection& contourMapProjection,
const std::vector<std::pair<size_t, double>>& matchingCells,
@@ -63,12 +69,14 @@ public:
static std::vector<CellIndexAndResult> cellOverlapVolumesAndResults( const RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
const cvf::Vec2d& globalPos2d,
const std::vector<double>& weightingResultValues );
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers );
static std::vector<CellIndexAndResult> cellRayIntersectionAndResults( const RigContourMapProjection& contourMapProjection,
const RigContourMapGrid& contourMapGrid,
const cvf::Vec2d& globalPos2d,
const std::vector<double>& weightingResultValues );
const std::vector<double>& weightingResultValues,
const std::set<int>& kLayers );
static bool isColumnResult( ResultAggregationType aggregationType );
static bool isMeanResult( ResultAggregationType aggregationType );
@@ -97,4 +105,6 @@ private:
static double calculateSum( const RigContourMapProjection& contourMapProjection,
const std::vector<std::pair<size_t, double>>& matchingCells,
const std::vector<double>& gridCellValues );
static bool isPointInsidePolygons( cvf::Vec2d point, const std::vector<std::vector<cvf::Vec3d>>& polygons );
};

View File

@@ -45,9 +45,12 @@ RigContourMapProjection::RigContourMapProjection( const RigContourMapGrid& conto
//--------------------------------------------------------------------------------------------------
std::vector<std::vector<std::pair<size_t, double>>>
RigContourMapProjection::generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation,
const std::vector<double>& weights )
const std::vector<double>& weights,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons )
{
m_projected3dGridIndices = RigContourMapCalculator::generateGridMapping( *this, m_contourMapGrid, resultAggregation, weights );
m_projected3dGridIndices =
RigContourMapCalculator::generateGridMapping( *this, m_contourMapGrid, resultAggregation, weights, kLayers, limitToPolygons );
return m_projected3dGridIndices;
}

View File

@@ -26,10 +26,12 @@
#include "cvfVector2.h"
#include <optional>
#include <set>
class RigContourMapGrid;
class RimGridView;
class RimRegularLegendConfig;
class RigPolyLinesData;
//==================================================================================================
///
@@ -87,7 +89,10 @@ public:
cvf::ref<cvf::UByteArray> getCellVisibility() const;
virtual std::vector<std::vector<std::pair<size_t, double>>>
generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation, const std::vector<double>& weights );
generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation,
const std::vector<double>& weights,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons );
double interpolateValue( const cvf::Vec2d& gridPosition2d ) const;

View File

@@ -18,6 +18,8 @@
#include "RigFormationNames.h"
#include <algorithm>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -137,3 +139,22 @@ void RigFormationNames::appendFormationRangeWithColor( const QString& name, cvf:
m_formationColors.push_back( color );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<int> RigFormationNames::findKLayers( std::vector<QString> formationNames )
{
std::set<int> foundK;
for ( int k = 1; k < (int)m_nameIndexPrKLayer.size(); k++ )
{
auto layerName = formationNameFromKLayerIdx( k );
if ( std::find( formationNames.begin(), formationNames.end(), layerName ) != formationNames.end() )
{
foundK.insert( k );
}
}
return foundK;
}

View File

@@ -21,6 +21,7 @@
#include "cvfObject.h"
#include <QString>
#include <set>
#include <vector>
#include "cvfColor3.h"
@@ -50,6 +51,8 @@ public:
void appendFormationRange( const QString& name, cvf::Color3f color, int kStartIdx, int kEndIdx );
void appendFormationRangeHeight( const QString& name, cvf::Color3f color, int kLayerCount );
std::set<int> findKLayers( std::vector<QString> formationNames );
private:
static cvf::Color3f undefinedColor();
void appendFormationRangeWithColor( const QString& name, cvf::Color3f color, int kStartIdx, int kEndIdx );

View File

@@ -43,7 +43,9 @@ RigStatisticsContourMapProjection::~RigStatisticsContourMapProjection()
std::vector<std::vector<std::pair<size_t, double>>>
RigStatisticsContourMapProjection::generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation,
const std::vector<double>& weights )
const std::vector<double>& weights,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons )
{
// The grid mapping is usually necessary to produce the data. For the statistics projection
// the data is already available, so we can just ignore it.

View File

@@ -40,7 +40,10 @@ public:
void generateAndSaveResults( const std::vector<double>& results );
std::vector<std::vector<std::pair<size_t, double>>>
generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation, const std::vector<double>& weights ) override;
generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation,
const std::vector<double>& weights,
const std::set<int>& kLayers,
const std::vector<std::vector<cvf::Vec3d>>& limitToPolygons ) override;
std::vector<bool> getMapCellVisibility( int viewStepIndex, RigContourMapCalculator::ResultAggregationType resultAggregation ) override;

View File

@@ -28,8 +28,8 @@
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "Formations/RimFormationNames.h"
#include "Rim2dIntersectionView.h"
#include "RimFormationNames.h"
#include "RimGeoMechCase.h"
#include "RimGeoMechResultDefinition.h"
#include "RimGeoMechView.h"

View File

@@ -32,6 +32,7 @@
#include "Well/RigWellResultFrame.h"
#include "Well/RigWellResultPoint.h"
#include "Formations/RimFormationNames.h"
#include "Rim2dIntersectionView.h"
#include "RimCellEdgeColors.h"
#include "RimEclipseCase.h"
@@ -39,7 +40,6 @@
#include "RimEclipseFaultColors.h"
#include "RimEclipseView.h"
#include "RimExtrudedCurveIntersection.h"
#include "RimFormationNames.h"
#include "RimIntersectionResultDefinition.h"
#include "RimMultipleEclipseResults.h"
#include "RimRegularLegendConfig.h"