Files
ResInsight/ApplicationLibCode/UnitTests/RigTimeCurveHistoryMerger-Test.cpp
T

289 lines
12 KiB
C++
Raw Normal View History

#include "gtest/gtest.h"
#include "RiaCurveMerger.h"
#include <cmath> // Needed for HUGE_VAL on Linux
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, TestDateInterpolation )
{
2020-11-06 09:46:38 +00:00
std::vector<double> values{ 2.0, 3.5, 5.0, 6.0 };
std::vector<time_t> timeSteps{ 1, 5, 10, 15 };
2025-06-13 14:36:16 +02:00
auto interpolationMethod = RiaCurveDefines::InterpolationMethod::LINEAR;
{
2025-06-13 14:36:16 +02:00
double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 1, timeSteps, values, interpolationMethod );
EXPECT_EQ( 2.0, val );
}
{
2025-06-13 14:36:16 +02:00
double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 0, timeSteps, values, interpolationMethod );
EXPECT_EQ( HUGE_VAL, val );
}
{
2025-06-13 14:36:16 +02:00
double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 20, timeSteps, values, interpolationMethod );
EXPECT_EQ( HUGE_VAL, val );
}
{
2025-06-13 14:36:16 +02:00
double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 3, timeSteps, values, interpolationMethod );
EXPECT_EQ( 2.75, val );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeSteps )
{
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ HUGE_VAL, 1.0, HUGE_VAL, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, HUGE_VAL };
std::vector<double> valuesB{ 10, 20, 30, 40, 45, HUGE_VAL, HUGE_VAL, 5.0, 6.0, HUGE_VAL };
EXPECT_EQ( valuesA.size(), valuesB.size() );
std::vector<time_t> timeSteps;
for ( size_t i = 0; i < 10; i++ )
{
timeSteps.push_back( i );
}
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeSteps, valuesA );
interpolate.addCurveData( timeSteps, valuesB );
interpolate.computeInterpolatedValues( true );
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ( 10, static_cast<int>( interpolatedTimeSteps.size() ) );
EXPECT_EQ( 3, static_cast<int>( intervals.size() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsOneComplete )
{
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
std::vector<double> valuesB{ 10, 20, 30, HUGE_VAL, 50, HUGE_VAL, 70 };
EXPECT_EQ( valuesA.size(), valuesB.size() );
std::vector<time_t> timeSteps;
for ( size_t i = 0; i < 7; i++ )
{
timeSteps.push_back( i );
}
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeSteps, valuesA );
interpolate.addCurveData( timeSteps, valuesB );
interpolate.computeInterpolatedValues( true );
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ( 7, static_cast<int>( interpolatedTimeSteps.size() ) );
EXPECT_EQ( 3, static_cast<int>( intervals.size() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsBothComplete )
{
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
std::vector<double> valuesB{ 10, 20, 30, 40, 50, 60, 70 };
EXPECT_EQ( valuesA.size(), valuesB.size() );
std::vector<time_t> timeSteps;
for ( size_t i = 0; i < 7; i++ )
{
timeSteps.push_back( i );
}
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeSteps, valuesA );
interpolate.addCurveData( timeSteps, valuesB );
interpolate.computeInterpolatedValues( true );
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ( 7, static_cast<int>( interpolatedTimeSteps.size() ) );
EXPECT_EQ( 1, static_cast<int>( intervals.size() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, OverlappintTimes )
{
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ 1, 2, 3, 4, 5 };
std::vector<double> valuesB{ 10, 20, 30, 40, 50 };
EXPECT_EQ( valuesA.size(), valuesB.size() );
2020-11-06 09:46:38 +00:00
std::vector<time_t> timeStepsA{ 0, 10, 11, 15, 20 };
std::vector<time_t> timeStepsB{ 1, 2, 3, 5, 7 };
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeStepsA, valuesA );
interpolate.addCurveData( timeStepsB, valuesB );
interpolate.computeInterpolatedValues( true );
EXPECT_EQ( 2, static_cast<int>( interpolate.curveCount() ) );
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ( 10, static_cast<int>( interpolatedTimeSteps.size() ) );
EXPECT_EQ( 1, static_cast<int>( intervals.size() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, RobustUse )
{
{
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR );
curveMerger.computeInterpolatedValues( true );
EXPECT_EQ( 0, static_cast<int>( curveMerger.allXValues().size() ) );
}
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ 1, 2, 3, 4, 5 };
std::vector<double> valuesB{ 10, 20, 30 };
2020-11-06 09:46:38 +00:00
std::vector<time_t> timeStepsA{ 0, 10, 11, 15, 20 };
std::vector<time_t> timeStepsB{ 1, 2, 3 };
{
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR );
curveMerger.addCurveData( timeStepsA, valuesA );
curveMerger.computeInterpolatedValues( true );
EXPECT_EQ( timeStepsA.size(), curveMerger.allXValues().size() );
EXPECT_EQ( timeStepsA.size(), curveMerger.interpolatedYValuesForAllXValues( 0 ).size() );
}
{
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR );
curveMerger.addCurveData( timeStepsA, valuesA );
curveMerger.addCurveData( timeStepsB, valuesB );
// Execute interpolation twice is allowed
curveMerger.computeInterpolatedValues( true );
curveMerger.computeInterpolatedValues( true );
EXPECT_EQ( 8, static_cast<int>( curveMerger.allXValues().size() ) );
EXPECT_EQ( 8, static_cast<int>( curveMerger.interpolatedYValuesForAllXValues( 0 ).size() ) );
EXPECT_EQ( 8, static_cast<int>( curveMerger.interpolatedYValuesForAllXValues( 1 ).size() ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, NoTimeStepOverlap )
{
2020-11-06 09:46:38 +00:00
std::vector<double> valuesA{ 1, 2, 3, 4, 5 };
std::vector<double> valuesB{ 10, 20, 30 };
2020-11-06 09:46:38 +00:00
std::vector<time_t> timeStepsA{ 0, 10, 11, 15, 20 };
std::vector<time_t> timeStepsB{ 100, 200, 300 };
{
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR );
curveMerger.addCurveData( timeStepsA, valuesA );
curveMerger.addCurveData( timeStepsB, valuesB );
// Execute interpolation twice is allowed
curveMerger.computeInterpolatedValues( true );
EXPECT_EQ( 8, static_cast<int>( curveMerger.allXValues().size() ) );
EXPECT_EQ( 0, static_cast<int>( curveMerger.validIntervalsForAllXValues().size() ) );
}
}
2024-12-03 16:53:11 +01:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, SharedXValues )
{
std::vector<double> valuesA{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
std::vector<double> valuesB{ 10, 20, 30, 40, 50, 60, 70 };
std::vector<time_t> timeSteps{ 1, 2, 3, 4, 5, 6, 7 };
2025-06-13 14:36:16 +02:00
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
2024-12-03 16:53:11 +01:00
interpolate.addCurveData( timeSteps, valuesA );
interpolate.addCurveData( timeSteps, valuesB );
interpolate.computeInterpolatedValues( true );
auto interpolatedTimeSteps = interpolate.allXValues();
EXPECT_TRUE( std::equal( timeSteps.begin(), timeSteps.end(), interpolatedTimeSteps.begin() ) );
auto generatedYValuesA = interpolate.interpolatedYValuesForAllXValues( 0 );
EXPECT_TRUE( std::equal( valuesA.begin(), valuesA.end(), generatedYValuesA.begin() ) );
auto generatedYValuesB = interpolate.interpolatedYValuesForAllXValues( 1 );
EXPECT_TRUE( std::equal( valuesB.begin(), valuesB.end(), generatedYValuesB.begin() ) );
}
//--------------------------------------------------------------------------------------------------
/// A curve where the value count is smaller than the time step count must not read out of bounds.
/// See https://github.com/OPM/ResInsight/issues/12810
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, FewerValuesThanTimeSteps )
{
std::vector<time_t> timeSteps{ 1, 2, 3, 4, 5, 6, 7 };
std::vector<double> partialValues{ 1.0, 2.0, 3.0, 4.0 };
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeSteps, partialValues );
interpolate.computeInterpolatedValues( true );
// The trailing time steps without a value are discarded
EXPECT_EQ( partialValues.size(), interpolate.allXValues().size() );
auto generatedValues = interpolate.interpolatedYValuesForAllXValues( 0 );
ASSERT_EQ( partialValues.size(), generatedValues.size() );
EXPECT_TRUE( std::equal( partialValues.begin(), partialValues.end(), generatedValues.begin() ) );
}
//--------------------------------------------------------------------------------------------------
/// Curves sharing time steps, but where one curve has fewer values, must not read out of bounds in
/// the shared-X code path. See https://github.com/OPM/ResInsight/issues/12810
//--------------------------------------------------------------------------------------------------
TEST( RiaTimeHistoryCurveMergerTest, SharedXValuesWithFewerValuesInOneCurve )
{
std::vector<time_t> timeSteps{ 1, 2, 3, 4, 5, 6, 7 };
std::vector<double> completeValues{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
std::vector<double> partialValues{ 10.0, 20.0, 30.0, 40.0 };
RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR );
interpolate.addCurveData( timeSteps, completeValues );
interpolate.addCurveData( timeSteps, partialValues );
interpolate.computeInterpolatedValues( true );
EXPECT_EQ( timeSteps.size(), interpolate.allXValues().size() );
auto generatedComplete = interpolate.interpolatedYValuesForAllXValues( 0 );
ASSERT_EQ( timeSteps.size(), generatedComplete.size() );
EXPECT_TRUE( std::equal( completeValues.begin(), completeValues.end(), generatedComplete.begin() ) );
auto generatedPartial = interpolate.interpolatedYValuesForAllXValues( 1 );
ASSERT_EQ( timeSteps.size(), generatedPartial.size() );
EXPECT_TRUE( std::equal( partialValues.begin(), partialValues.end(), generatedPartial.begin() ) );
// No data is available for the time steps beyond the last value
for ( size_t i = partialValues.size(); i < generatedPartial.size(); i++ )
{
EXPECT_EQ( HUGE_VAL, generatedPartial[i] );
}
}