From cfcbc03794aa1451aef93dfe485e4ba4662f1074 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 2 Apr 2025 15:33:16 +0200 Subject: [PATCH] #12305 Well Target Mapping: add filter by view Fixes #12305. --- .../ProjectDataModel/RimWellTargetMapping.cpp | 59 ++++++++++++++++++- .../ProjectDataModel/RimWellTargetMapping.h | 5 ++ .../Well/RigWellTargetMapping.cpp | 13 ++-- .../Well/RigWellTargetMapping.h | 1 + 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.cpp b/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.cpp index 1393c0570d..1339ec0552 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.cpp @@ -20,9 +20,11 @@ #include "RiaGuiApplication.h" #include "RiaLogging.h" +#include "RiaOptionItemFactory.h" #include "RiaPorosityModel.h" #include "RiaResultNames.h" +#include "RigActiveCellInfo.h" #include "RiuMainWindow.h" #include "RigCaseCellResultsData.h" @@ -148,6 +150,8 @@ RimWellTargetMapping::RimWellTargetMapping() caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_generateButton ); m_generateButton.xmlCapability()->disableIO(); + CAF_PDM_InitFieldNoDefault( &m_filterView, "FilterView", "Filter By View" ); + CAF_PDM_InitFieldNoDefault( &m_ensembleStatisticsCase, "EnsembleStatisticsCase", "Ensemble Statistics Case" ); m_minimumSaturationOil = cvf::UNDEFINED_DOUBLE; @@ -235,6 +239,18 @@ QList RimWellTargetMapping::calculateValueOptions( const caf::AppEnum::setEnumSubset( &m_volumesType, findAvailableVolumesTypes( fc ) ); } } + else if ( fieldNeedingOptions == &m_filterView ) + { + options.push_back( caf::PdmOptionItemInfo( "None", nullptr ) ); + + if ( auto fc = firstCase() ) + { + for ( const auto& view : fc->views() ) + { + RiaOptionItemFactory::appendOptionItemFromViewNameAndCaseName( view, &options ); + } + } + } return options; } @@ -489,6 +505,9 @@ void RimWellTargetMapping::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd resultGroup->add( &m_volumesType ); + auto hasEnsembleParent = firstAncestorOrThisOfType() != nullptr; + if ( !hasEnsembleParent ) uiOrdering.add( &m_filterView ); + caf::PdmUiGroup* minimumCellValuesGroup = uiOrdering.addNewGroup( "Minimum Cell Values" ); if ( showOilOptions ) minimumCellValuesGroup->add( &m_saturationOil ); if ( showGasOptions ) minimumCellValuesGroup->add( &m_saturationGas ); @@ -497,8 +516,6 @@ void RimWellTargetMapping::defineUiOrdering( QString uiConfigName, caf::PdmUiOrd minimumCellValuesGroup->add( &m_transmissibility ); minimumCellValuesGroup->add( &m_resetDefaultButton ); - auto hasEnsembleParent = firstAncestorOrThisOfType() != nullptr; - if ( hasEnsembleParent ) { caf::PdmUiGroup* ensembleGridGroup = uiOrdering.addNewGroup( "Ensemble Statistics Grid" ); @@ -533,7 +550,43 @@ RigWellTargetMapping::ClusteringLimits RimWellTargetMapping::getClusteringLimits .transmissibility = m_transmissibility, .maxNumTargets = m_maxNumTargets, .maxIterations = m_maxIterations, - .filterAddress = m_resultDefinition->eclipseResultAddress() }; + .filterAddress = m_resultDefinition->eclipseResultAddress(), + .filter = getVisibilityFilter() }; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimWellTargetMapping::getVisibilityFilter() const +{ + std::vector filter = {}; + + // Visibility filter is only valid in the single case setting + auto hasEnsembleParent = firstAncestorOrThisOfType() != nullptr; + if ( !hasEnsembleParent ) + { + auto fc = firstCase(); + if ( m_filterView() && fc ) + { + cvf::ref visibility = m_filterView->currentTotalCellVisibility(); + + auto activeReservoirCellIndices = + fc->eclipseCaseData()->activeCellInfo( RiaDefines::PorosityModelType::MATRIX_MODEL )->activeReservoirCellIndices(); + int numActiveCells = static_cast( activeReservoirCellIndices.size() ); + + filter.resize( numActiveCells, std::numeric_limits::infinity() ); + + // Create binary filter for active cells: 1.0 can be used, 0.0 is filtered out. +#pragma omp parallel for + for ( int i = 0; i < numActiveCells; i++ ) + { + const auto reservoirCellIndex = activeReservoirCellIndices[i]; + filter[i] = visibility->val( reservoirCellIndex ) ? 1.0 : 0.0; + } + } + } + + return filter; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.h b/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.h index f60bad9aa9..474fa1fa9f 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.h +++ b/ApplicationLibCode/ProjectDataModel/RimWellTargetMapping.h @@ -21,12 +21,14 @@ #include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmPtrField.h" #include "RigFloodingSettings.h" #include "Well/RigWellTargetMapping.h" class RimEclipseResultDefinition; class RimEclipseCase; +class RimEclipseView; //================================================================================================== /// @@ -66,6 +68,7 @@ private: static std::vector findAvailableVolumesTypes( RimEclipseCase* eclipseCase ); RigWellTargetMapping::ClusteringLimits getClusteringLimits() const; + std::vector getVisibilityFilter() const; void resetMinimumCellValuesToDefault(); @@ -98,6 +101,8 @@ private: caf::PdmField m_generateButton; + caf::PdmPtrField m_filterView; + caf::PdmChildField m_ensembleStatisticsCase; double m_minimumSaturationOil; diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.cpp b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.cpp index bef783146b..5c584a1d5e 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.cpp @@ -145,15 +145,20 @@ void RigWellTargetMapping::generateCandidates( RimEclipseCase* eclips } std::vector filterVector; - if ( limits.filterAddress.isValid() ) + if ( !limits.filter.empty() ) + { + filterVector = limits.filter; + } + else if ( limits.filterAddress.isValid() ) { resultsData->ensureKnownResultLoaded( limits.filterAddress ); filterVector = resultsData->cellScalarResults( limits.filterAddress, timeStepIdx ); } - else + + // Disable filtering if not configured: set all items to 1 (which includes all cells). + if ( filterVector.empty() || filterVector.size() != data.pressure.size() ) { - // Disable filter on invalid address: set all items to 1 (which includes all cells). - filterVector.resize( data.pressure.size(), 1.0 ); + filterVector = std::vector( data.pressure.size(), 1.0 ); } std::vector clusters( activeCellCount.value(), 0 ); diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.h b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.h index 8e7bdcc241..12899abddb 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.h +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetMapping.h @@ -78,6 +78,7 @@ public: int maxNumTargets; int maxIterations; RigEclipseResultAddress filterAddress; + std::vector filter; }; struct DataContainer