WIP: generate well target candidates statistics

This commit is contained in:
Kristian Bendiksen 2024-10-02 09:12:49 +02:00
parent 53a31c88c9
commit b5cde7e883
4 changed files with 134 additions and 20 deletions

View File

@ -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<caf::PdmOptionItemInfo> RimWellTargetCandidatesGenerator::calculateValueOp
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_timeStep )
if ( fieldNeedingOptions == &m_targetCase )
{
auto ensemble = firstAncestorOrThisOfType<RimEclipseCaseEnsemble>();
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<RimEclipseCaseEnsemble>();
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<caf::PdmUiPushButtonEditorAttribute*>( 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<RimEclipseCaseEnsemble>();
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;
}

View File

@ -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<int> m_timeStep;
RigWellTargetCandidatesGenerator::ClusteringLimits getClusteringLimits() const;
caf::PdmPtrField<RimEclipseCase*> m_targetCase;
caf::PdmField<int> m_timeStep;
caf::PdmField<caf::AppEnum<RigWellTargetCandidatesGenerator::VolumeType>> m_volumeType;
caf::PdmField<caf::AppEnum<RigWellTargetCandidatesGenerator::VolumeResultType>> m_volumeResultType;
@ -57,8 +64,9 @@ private:
caf::PdmField<double> m_permeability;
caf::PdmField<double> m_transmissibility;
caf::PdmField<int> m_maxIterations;
caf::PdmField<int> m_maxClusters;
caf::PdmField<int> m_maxIterations;
caf::PdmField<int> m_maxClusters;
caf::PdmField<bool> m_generateEnsembleStatistics;
double m_minimumVolume;
double m_maximumVolume;

View File

@ -602,3 +602,53 @@ std::vector<RigWellTargetCandidatesGenerator::ClusterStatistics>
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<int> occupancy( targetNumActiveCells, 0 );
std::vector<double> pressure( numGrids, std::numeric_limits<double>::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<double> 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]++;
}
}
}
}
}

View File

@ -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: