From b5cde7e8831efe99354f5a563a47eaeca5182040 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 2 Oct 2024 09:12:49 +0200 Subject: [PATCH] WIP: generate well target candidates statistics --- .../RimWellTargetCandidatesGenerator.cpp | 79 +++++++++++++++---- .../RimWellTargetCandidatesGenerator.h | 16 +++- .../Well/RigWellTargetCandidatesGenerator.cpp | 50 ++++++++++++ .../Well/RigWellTargetCandidatesGenerator.h | 9 +++ 4 files changed, 134 insertions(+), 20 deletions(-) diff --git a/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.cpp b/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.cpp index fe4cdf04fb..2af7fa7550 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.cpp @@ -33,6 +33,7 @@ #include "RimTools.h" #include "cafPdmUiDoubleSliderEditor.h" +#include "cafPdmUiPushButtonEditor.h" #include "cafPdmUiSliderTools.h" #include "cvfMath.h" @@ -79,6 +80,7 @@ RimWellTargetCandidatesGenerator::RimWellTargetCandidatesGenerator() { CAF_PDM_InitObject( "Well Target Candidates Generator" ); + CAF_PDM_InitFieldNoDefault( &m_targetCase, "TargetCase", "Target Case" ); CAF_PDM_InitField( &m_timeStep, "TimeStep", 0, "Time Step" ); CAF_PDM_InitFieldNoDefault( &m_volumeType, "VolumeType", "Volume" ); @@ -100,6 +102,9 @@ RimWellTargetCandidatesGenerator::RimWellTargetCandidatesGenerator() CAF_PDM_InitField( &m_maxIterations, "Iterations", 10000, "Max Iterations" ); CAF_PDM_InitField( &m_maxClusters, "MaxClusters", 5, "Max Clusters" ); + CAF_PDM_InitField( &m_generateEnsembleStatistics, "GenerateEnsembleStatistics", true, "Generate Ensemble Statistics" ); + caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_generateEnsembleStatistics ); + m_minimumVolume = cvf::UNDEFINED_DOUBLE; m_maximumVolume = cvf::UNDEFINED_DOUBLE; @@ -126,8 +131,12 @@ RimWellTargetCandidatesGenerator::~RimWellTargetCandidatesGenerator() void RimWellTargetCandidatesGenerator::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { updateAllBoundaries(); + generateCandidates( m_targetCase() ); - generateCandidates(); + if ( changedField == &m_generateEnsembleStatistics ) + { + generateEnsembleStatistics(); + } } //-------------------------------------------------------------------------------------------------- @@ -137,7 +146,19 @@ QList RimWellTargetCandidatesGenerator::calculateValueOp { QList options; - if ( fieldNeedingOptions == &m_timeStep ) + if ( fieldNeedingOptions == &m_targetCase ) + { + auto ensemble = firstAncestorOrThisOfType(); + if ( !ensemble ) return options; + + if ( ensemble->cases().empty() ) return options; + + for ( auto eclipseCase : ensemble->cases() ) + { + options.push_back( caf::PdmOptionItemInfo( eclipseCase->caseUserDescription(), eclipseCase, false, eclipseCase->uiIconProvider() ) ); + } + } + else if ( fieldNeedingOptions == &m_timeStep ) { auto ensemble = firstAncestorOrThisOfType(); if ( ensemble && !ensemble->cases().empty() ) @@ -257,29 +278,42 @@ void RimWellTargetCandidatesGenerator::defineEditorAttribute( const caf::PdmFiel doubleAttributes->m_decimals = 3; } } + + if ( field == &m_generateEnsembleStatistics ) + { + caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast( attribute ); + if ( attrib ) + { + attrib->m_buttonText = "Create Ensemble Statistics"; + } + } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellTargetCandidatesGenerator::generateCandidates() +void RimWellTargetCandidatesGenerator::generateCandidates( RimEclipseCase* eclipseCase ) +{ + RigWellTargetCandidatesGenerator::ClusteringLimits limits = getClusteringLimits(); + RigWellTargetCandidatesGenerator::generateCandidates( eclipseCase, m_timeStep(), m_volumeType(), m_volumesType(), m_volumeResultType(), limits ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellTargetCandidatesGenerator::generateEnsembleStatistics() { auto ensemble = firstAncestorOrThisOfType(); if ( !ensemble ) return; - if ( ensemble->cases().empty() ) return; - - RimEclipseCase* eclipseCase = ensemble->cases().front(); - - RigWellTargetCandidatesGenerator::ClusteringLimits limits; - limits.volume = m_volume; - limits.permeability = m_permeability; - limits.pressure = m_pressure; - limits.transmissibility = m_transmissibility; - limits.maxClusters = m_maxClusters; - limits.maxIterations = m_maxIterations; - - RigWellTargetCandidatesGenerator::generateCandidates( eclipseCase, m_timeStep(), m_volumeType(), m_volumesType(), m_volumeResultType(), limits ); + RigWellTargetCandidatesGenerator::ClusteringLimits limits = getClusteringLimits(); + RigWellTargetCandidatesGenerator::generateEnsembleCandidates( *m_targetCase(), + *ensemble, + m_timeStep(), + m_volumeType(), + m_volumesType(), + m_volumeResultType(), + limits ); } //-------------------------------------------------------------------------------------------------- @@ -294,3 +328,16 @@ void RimWellTargetCandidatesGenerator::defineUiOrdering( QString uiConfigName, c updateAllBoundaries(); } } + +RigWellTargetCandidatesGenerator::ClusteringLimits RimWellTargetCandidatesGenerator::getClusteringLimits() const +{ + RigWellTargetCandidatesGenerator::ClusteringLimits limits; + limits.volume = m_volume; + limits.permeability = m_permeability; + limits.pressure = m_pressure; + limits.transmissibility = m_transmissibility; + limits.maxClusters = m_maxClusters; + limits.maxIterations = m_maxIterations; + + return limits; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.h b/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.h index b9334226bf..3b44eb6473 100644 --- a/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.h +++ b/ApplicationLibCode/ProjectDataModel/RimWellTargetCandidatesGenerator.h @@ -21,9 +21,12 @@ #include "cafAppEnum.h" #include "cafPdmField.h" #include "cafPdmObject.h" +#include "cafPdmPtrField.h" #include "Well/RigWellTargetCandidatesGenerator.h" +class RimEclipseCase; + //================================================================================================== /// /// @@ -43,10 +46,14 @@ protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; private: - void generateCandidates(); + void generateCandidates( RimEclipseCase* eclipseCase ); void updateAllBoundaries(); + void generateEnsembleStatistics(); - caf::PdmField m_timeStep; + RigWellTargetCandidatesGenerator::ClusteringLimits getClusteringLimits() const; + + caf::PdmPtrField m_targetCase; + caf::PdmField m_timeStep; caf::PdmField> m_volumeType; caf::PdmField> m_volumeResultType; @@ -57,8 +64,9 @@ private: caf::PdmField m_permeability; caf::PdmField m_transmissibility; - caf::PdmField m_maxIterations; - caf::PdmField m_maxClusters; + caf::PdmField m_maxIterations; + caf::PdmField m_maxClusters; + caf::PdmField m_generateEnsembleStatistics; double m_minimumVolume; double m_maximumVolume; diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp index 718512f32f..d3211a82ac 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp @@ -602,3 +602,53 @@ std::vector return statistics; } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellTargetCandidatesGenerator::generateEnsembleCandidates( RimEclipseCase& targetCase, + RimEclipseCaseEnsemble& ensemble, + size_t timeStepIdx, + VolumeType volumeType, + VolumesType volumesType, + VolumeResultType volumeResultType, + const ClusteringLimits& limits ) +{ + for ( auto eclipseCase : ensemble.cases() ) + { + generateCandidates( eclipseCase, timeStepIdx, volumeType, volumesType, volumeResultType, limits ); + } + + const RigCaseCellResultsData* targetResultsData = targetCase.results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + const RigActiveCellInfo* targetActiveCellInfo = targetResultsData->activeCellInfo(); + + const size_t targetNumReservoirCells = targetActiveCellInfo->reservoirCellCount(); + const size_t targetNumActiveCells = targetActiveCellInfo->reservoirActiveCellCount(); + const int numGrids = ensemble.cases().size(); + + std::vector occupancy( targetNumActiveCells, 0 ); + std::vector pressure( numGrids, std::numeric_limits::infinity() ); + for ( auto eclipseCase : ensemble.cases() ) + { + const RigCaseCellResultsData* resultsData = eclipseCase->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + const RigMainGrid* mainGrid = eclipseCase->mainGrid(); + const RigActiveCellInfo* activeCellInfo = resultsData->activeCellInfo(); + + std::vector clusterNum; + for ( size_t targetCellIdx = 0; targetCellIdx < targetNumReservoirCells; targetCellIdx++ ) + { + const RigCell& nativeCell = targetCase.mainGrid()->globalCellArray()[targetCellIdx]; + cvf::Vec3d cellCenter = nativeCell.center(); + + size_t cellIdx = mainGrid->findReservoirCellIndexFromPoint( cellCenter ); + if ( cellIdx != cvf::UNDEFINED_SIZE_T && activeCellInfo->isActive( cellIdx ) ) + { + size_t resultIndex = targetResultsData->activeCellInfo()->cellResultIndex( cellIdx ); + if ( clusterNum[resultIndex] > 0 ) + { + occupancy[resultIndex]++; + } + } + } + } +} diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h index 0f93e9b875..7e0a395d02 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h @@ -27,6 +27,7 @@ class RigActiveCellInfo; class RigCaseCellResultsData; class RimEclipseCase; +class RimEclipseCaseEnsemble; //================================================================================================== /// /// @@ -77,6 +78,14 @@ public: VolumeResultType volumeResultType, size_t timeStepIdx ); + static void generateEnsembleCandidates( RimEclipseCase& targetCase, + RimEclipseCaseEnsemble& ensemble, + size_t timeStepIdx, + VolumeType volumeType, + VolumesType volumesType, + VolumeResultType volumeResultType, + const ClusteringLimits& limits ); + class ClusterStatistics { public: