mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 06:38:13 -05:00
#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:
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;
|
||||
|
||||
|
||||
Reference in new issue
Block a user