From 6d642d85eec8e5fca66c967b62be03f87beddef5 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 6 Dec 2024 11:58:21 +0100 Subject: [PATCH] Cluster statistics across realizations. --- .../Well/RigWellTargetCandidatesGenerator.cpp | 101 +++++++++++++++++- .../Well/RigWellTargetCandidatesGenerator.h | 4 + 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp index add5f31fe4..112162fd94 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.cpp @@ -27,6 +27,7 @@ #include "RigCaseCellResultsData.h" #include "RigEclipseResultAddress.h" #include "RigMainGrid.h" +#include "RigStatisticsMath.h" #include "RimEclipseCase.h" #include "RimEclipseCaseEnsemble.h" @@ -188,6 +189,9 @@ void RigWellTargetCandidatesGenerator::generateCandidates( RimEclipseCase* RiaLogging::info( QString( "Total FIPGAS: %1" ).arg( s.totalFipGas ) ); RiaLogging::info( QString( "Average Permeability: %1" ).arg( s.permeability ) ); RiaLogging::info( QString( "Average Pressure: %1" ).arg( s.pressure ) ); + + QString clusterPorvSoil = "CLUSTER_TOTAL_PORV_SOIL"; + createResultVector( *eclipseCase, clusterPorvSoil, clusters, s.totalPorvSoil ); } } @@ -404,6 +408,58 @@ void RigWellTargetCandidatesGenerator::createResultVector( RimEclipseCase& resultsData->recalculateStatistics( resultAddress ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellTargetCandidatesGenerator::createResultVector( RimEclipseCase& eclipseCase, const QString& resultName, const std::vector& values ) +{ + RigEclipseResultAddress resultAddress( RiaDefines::ResultCatType::GENERATED, resultName ); + + auto resultsData = eclipseCase.results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + + resultsData->addStaticScalarResult( RiaDefines::ResultCatType::GENERATED, resultName, false, values.size() ); + + std::vector* resultVector = resultsData->modifiableCellScalarResult( resultAddress, 0 ); + resultVector->resize( values.size(), std::numeric_limits::infinity() ); + + for ( size_t idx = 0; idx < values.size(); idx++ ) + { + resultVector->at( idx ) = values[idx]; + } + + resultsData->recalculateStatistics( resultAddress ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigWellTargetCandidatesGenerator::createResultVector( RimEclipseCase& eclipseCase, + const QString& resultName, + const std::vector& clusterIds, + double value ) +{ + RigEclipseResultAddress resultAddress( RiaDefines::ResultCatType::GENERATED, resultName ); + + auto resultsData = eclipseCase.results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + + resultsData->addStaticScalarResult( RiaDefines::ResultCatType::GENERATED, resultName, false, clusterIds.size() ); + + std::vector* resultVector = resultsData->modifiableCellScalarResult( resultAddress, 0 ); + resultVector->resize( clusterIds.size(), std::numeric_limits::infinity() ); + + std::fill( resultVector->begin(), resultVector->end(), std::numeric_limits::infinity() ); + + for ( size_t idx = 0; idx < clusterIds.size(); idx++ ) + { + if ( clusterIds[idx] > 0 ) + { + resultVector->at( idx ) = value; + } + } + + resultsData->recalculateStatistics( resultAddress ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -623,7 +679,7 @@ void RigWellTargetCandidatesGenerator::generateEnsembleCandidates( RimEclipseCas for ( auto eclipseCase : ensemble.cases() ) { - auto task = progInfo.task( "Generating statistics", 1 ); + auto task = progInfo.task( "Generating realization statistics.", 1 ); generateCandidates( eclipseCase, timeStepIdx, volumeType, volumesType, volumeResultType, limits ); } @@ -635,6 +691,9 @@ void RigWellTargetCandidatesGenerator::generateEnsembleCandidates( RimEclipseCas const size_t targetNumActiveCells = targetActiveCellInfo->reservoirActiveCellCount(); std::vector occupancy( targetNumActiveCells, 0 ); + + std::vector> porvSoilSamples; + for ( auto eclipseCase : ensemble.cases() ) { auto task = progInfo.task( "Accumulating results.", 1 ); @@ -647,6 +706,13 @@ void RigWellTargetCandidatesGenerator::generateEnsembleCandidates( RimEclipseCas resultsData->ensureKnownResultLoaded( clustersNumAddress ); const std::vector& clusterNum = resultsData->cellScalarResults( clustersNumAddress, 0 ); + QString clusterPorvSoil = "CLUSTER_TOTAL_PORV_SOIL"; + RigEclipseResultAddress clusterPorvSoilAddress( RiaDefines::ResultCatType::GENERATED, clusterPorvSoil ); + resultsData->ensureKnownResultLoaded( clusterPorvSoilAddress ); + const std::vector& porvSoil = resultsData->cellScalarResults( clusterPorvSoilAddress, 0 ); + + std::vector totalPorvSoil( targetNumActiveCells, std::numeric_limits::infinity() ); + for ( size_t targetCellIdx = 0; targetCellIdx < targetNumReservoirCells; targetCellIdx++ ) { const RigCell& nativeCell = targetCase.mainGrid()->cell( targetCellIdx ); @@ -661,10 +727,43 @@ void RigWellTargetCandidatesGenerator::generateEnsembleCandidates( RimEclipseCas if ( !std::isinf( clusterNum[resultIndex] ) && clusterNum[resultIndex] > 0 ) { occupancy[targetResultIndex]++; + totalPorvSoil[targetResultIndex] = porvSoil[resultIndex]; } } } + + porvSoilSamples.push_back( totalPorvSoil ); + } + + int nCells = static_cast( targetNumActiveCells ); + std::vector p10Results( nCells, std::numeric_limits::infinity() ); + std::vector p50Results( nCells, std::numeric_limits::infinity() ); + std::vector p90Results( nCells, std::numeric_limits::infinity() ); + std::vector meanResults( nCells, std::numeric_limits::infinity() ); + std::vector minResults( nCells, std::numeric_limits::infinity() ); + std::vector maxResults( nCells, std::numeric_limits::infinity() ); + +#pragma omp parallel for + for ( int i = 0; i < nCells; i++ ) + { + size_t numSamples = porvSoilSamples.size(); + std::vector samples( numSamples, 0.0 ); + for ( size_t s = 0; s < numSamples; s++ ) + samples[s] = porvSoilSamples[s][i]; + + double p10, p50, p90, mean; + RigStatisticsMath::calculateStatisticsCurves( samples, &p10, &p50, &p90, &mean, RigStatisticsMath::PercentileStyle::SWITCHED ); + + p10Results[i] = p10; + p50Results[i] = p50; + p90Results[i] = p90; + printf( "P90[%d] => %f\n", i, p90 ); + meanResults[i] = mean; + + minResults[i] = RiaStatisticsTools::minimumValue( samples ); + maxResults[i] = RiaStatisticsTools::maximumValue( samples ); } createResultVector( targetCase, "OCCUPANCY", occupancy ); + createResultVector( targetCase, "CLUSTER_TOTAL_PORV_SOIL_P90", p90Results ); } diff --git a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h index 7e0a395d02..c5083a7e23 100644 --- a/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h +++ b/ApplicationLibCode/ReservoirDataModel/Well/RigWellTargetCandidatesGenerator.h @@ -165,6 +165,10 @@ class RigWellTargetCandidatesGenerator static void createResultVector( RimEclipseCase& eclipseCase, const QString& resultName, const std::vector& clusterIds ); + static void createResultVector( RimEclipseCase& eclipseCase, const QString& resultName, const std::vector& values ); + + static void createResultVector( RimEclipseCase& eclipseCase, const QString& resultName, const std::vector& clusterIds, double value ); + static double getValueForFace( const std::vector& x, const std::vector& y, const std::vector& z,