#14345 Grid Calculation: replace undefined values with default value in aggregations

Aggregation functions like sum() in the expression parser include all
values in the input vector. Undefined values (HUGE_VAL) could leak into
the aggregation input when a grid case group member has fewer time steps
on disk than the main case it inherits result meta data from, or when a
cell is active in the calculation case but has no value in the source
data. This produced infinite sums for some realizations, while the
histogram statistics ignore undefined values.

Replace undefined values in the aggregation input with the default value
0.0, matching the histogram semantics, and log a warning per case and
variable when values were replaced.
This commit is contained in:
Kristian Bendiksen committed 2026-09-16 10:53:31 +02:00
1 parent 0579dbb468
commit 0ad61a004a
4 files changed
+112 -4

No files matched your search

@@ -35,6 +35,7 @@
#include "RigResultAccessor.h"
#include "RigResultAccessorFactory.h"
#include "RigStatisticsMath.h"
#include "RigStatisticsTools.h"
#include "RimCaseCollection.h"
#include "RimEclipseCase.h"
@@ -721,6 +722,27 @@ void RimGridCalculation::replaceFilteredValuesWithDefaultValue( double
}
}
//--------------------------------------------------------------------------------------------------
/// Replace undefined values (infinity and NaN) with the given default value. Returns the number of
/// replaced values.
//--------------------------------------------------------------------------------------------------
size_t RimGridCalculation::replaceInvalidValuesWithDefaultValue( double defaultValue, std::vector<double>& values )
{
size_t replacedCount = 0;
#pragma omp parallel for reduction( + : replacedCount )
for ( int i = 0; i < static_cast<int>( values.size() ); i++ )
{
if ( RigStatisticsTools::isInvalidNumber( values[i] ) )
{
values[i] = defaultValue;
replacedCount++;
}
}
return replacedCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -915,6 +937,7 @@ bool RimGridCalculation::calculateForCases( const std::vector<RimEclipseCase*>&
scalarResultFrames->resize( timeStepCount );
std::vector<double> aggregatedValuesOneTimeStep;
std::vector<size_t> invalidValueCountPerVariable( m_variables.size(), 0 );
for ( size_t tsId = 0; tsId < timeStepCount; tsId++ )
{
@@ -936,11 +959,19 @@ bool RimGridCalculation::calculateForCases( const std::vector<RimEclipseCase*>&
{
RiaLogging::error( std::format( " No data found for variable '{}'.", v->name() ) );
}
else if ( inputValueVisibilityFilter && hasAggregationExpression )
else if ( hasAggregationExpression )
{
const double defaultValue = 0.0;
auto activeCellInfo = calculationCase->eclipseCaseData()->activeCellInfo( porosityModel );
replaceFilteredValuesWithDefaultValue( defaultValue, inputValueVisibilityFilter, dataForVariable, activeCellInfo );
const double defaultValue = 0.0;
if ( inputValueVisibilityFilter )
{
auto activeCellInfo = calculationCase->eclipseCaseData()->activeCellInfo( porosityModel );
replaceFilteredValuesWithDefaultValue( defaultValue, inputValueVisibilityFilter, dataForVariable, activeCellInfo );
}
// Aggregation functions include all values in the vector. Replace undefined values with the
// default value to avoid contaminating aggregated values like sum() with infinity. Undefined
// values are ignored by other statistics computations, like the histogram in the 3d view.
invalidValueCountPerVariable[i] += replaceInvalidValuesWithDefaultValue( defaultValue, dataForVariable );
}
dataForAllVariables.push_back( dataForVariable );
@@ -1012,6 +1043,18 @@ bool RimGridCalculation::calculateForCases( const std::vector<RimEclipseCase*>&
calculationCase->updateResultAddressCollection();
}
for ( size_t i = 0; i < m_variables.size(); i++ )
{
if ( invalidValueCountPerVariable[i] > 0 )
{
RiaLogging::warning( std::format( " Variable '{}': {} undefined input values were replaced with 0.0 for case '{}'. The "
"input result may be missing data for some cells or time steps.",
m_variables[i]->name().toStdString(),
invalidValueCountPerVariable[i],
calculationCase->caseUserDescription().toStdString() ) );
}
}
if ( hasAggregationExpression )
{
QString txt = " " + calculationCase->caseUserDescription();
@@ -86,6 +86,8 @@ public:
RimGridCalculationVariable* createVariable() override;
static size_t replaceInvalidValuesWithDefaultValue( double defaultValue, std::vector<double>& values );
protected:
void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& updatedObjects ) override;