From 2ef822e491c15e17ed41a969c1feaecc1430e537 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 29 May 2020 14:38:18 +0200 Subject: [PATCH] #6007 Add utility for linear interpolation. --- .../Application/Tools/CMakeLists_files.cmake | 2 + .../Tools/RiaInterpolationTools.cpp | 66 ++++++++++++++++ .../Application/Tools/RiaInterpolationTools.h | 30 +++++++ .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RiaInterpolationTools-Test.cpp | 79 +++++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 ApplicationCode/Application/Tools/RiaInterpolationTools.cpp create mode 100644 ApplicationCode/Application/Tools/RiaInterpolationTools.h create mode 100644 ApplicationCode/UnitTests/RiaInterpolationTools-Test.cpp diff --git a/ApplicationCode/Application/Tools/CMakeLists_files.cmake b/ApplicationCode/Application/Tools/CMakeLists_files.cmake index fecc4cb5bf..0f7a05f315 100644 --- a/ApplicationCode/Application/Tools/CMakeLists_files.cmake +++ b/ApplicationCode/Application/Tools/CMakeLists_files.cmake @@ -16,6 +16,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaQDateTimeTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaWellNameComparer.h ${CMAKE_CURRENT_LIST_DIR}/RiaStdStringTools.h +${CMAKE_CURRENT_LIST_DIR}/RiaInterpolationTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer.h ${CMAKE_CURRENT_LIST_DIR}/RiaSimWellBranchTools.h ${CMAKE_CURRENT_LIST_DIR}/RiaProjectFileVersionTools.h @@ -62,6 +63,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaQDateTimeTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaWellNameComparer.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaStdStringTools.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaInterpolationTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSimWellBranchTools.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaProjectFileVersionTools.cpp diff --git a/ApplicationCode/Application/Tools/RiaInterpolationTools.cpp b/ApplicationCode/Application/Tools/RiaInterpolationTools.cpp new file mode 100644 index 0000000000..7c22f5b83c --- /dev/null +++ b/ApplicationCode/Application/Tools/RiaInterpolationTools.cpp @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RiaInterpolationTools.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RiaInterpolationTools::linear( const std::vector& x, const std::vector& y, double value ) +{ + assert( x.size() == y.size() ); + + // Handle cases with only one data point. + if ( x.size() == 1 ) + { + return std::numeric_limits::infinity(); + } + + // Find the lower boundary + bool found = false; + int lowerIndex = 0; + for ( int i = 0; i < static_cast( x.size() - 1 ); i++ ) + { + if ( x[i] < value && x[i + 1] > value ) + { + lowerIndex = i; + found = true; + } + } + + // Value is outside of the defined range + if ( !found ) + { + return std::numeric_limits::infinity(); + } + + int upperIndex = lowerIndex + 1; + + double lowerX = x[lowerIndex]; + double lowerY = y[lowerIndex]; + double upperX = x[upperIndex]; + double upperY = y[upperIndex]; + + double deltaY = upperY - lowerY; + double deltaX = upperX - lowerX; + + return lowerY + ( ( value - lowerX ) / deltaX ) * deltaY; +} diff --git a/ApplicationCode/Application/Tools/RiaInterpolationTools.h b/ApplicationCode/Application/Tools/RiaInterpolationTools.h new file mode 100644 index 0000000000..745046d5a7 --- /dev/null +++ b/ApplicationCode/Application/Tools/RiaInterpolationTools.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2020 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +//================================================================================================== +// +//================================================================================================== +class RiaInterpolationTools +{ +public: + static double linear( const std::vector& x, const std::vector& y, double value ); +}; diff --git a/ApplicationCode/UnitTests/CMakeLists_files.cmake b/ApplicationCode/UnitTests/CMakeLists_files.cmake index 1724e096ba..ece04995a8 100644 --- a/ApplicationCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationCode/UnitTests/CMakeLists_files.cmake @@ -62,6 +62,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaSummaryCurveAnalyzer-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaStdStringTools-Test.cpp +${CMAKE_CURRENT_LIST_DIR}/RiaInterpolationTools-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifWellMeasurementReader-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RiaDateStringParser-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RigHexGradientTools-Test.cpp diff --git a/ApplicationCode/UnitTests/RiaInterpolationTools-Test.cpp b/ApplicationCode/UnitTests/RiaInterpolationTools-Test.cpp new file mode 100644 index 0000000000..92f4da3e85 --- /dev/null +++ b/ApplicationCode/UnitTests/RiaInterpolationTools-Test.cpp @@ -0,0 +1,79 @@ +#include "gtest/gtest.h" + +#include "RiaInterpolationTools.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, LinearEmptyData ) +{ + std::vector x; + std::vector y; + + double res = RiaInterpolationTools::linear( x, y, 99.9 ); + EXPECT_EQ( std::numeric_limits::infinity(), res ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, SingleValue ) +{ + std::vector x = { 1.0 }; + std::vector y = { 3.0 }; + + double res = RiaInterpolationTools::linear( x, y, 2.0 ); + EXPECT_EQ( std::numeric_limits::infinity(), res ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, ValidInterval ) +{ + std::vector x = { 0.0, 1.0 }; + std::vector y = { 0.0, 2.0 }; + + double res = RiaInterpolationTools::linear( x, y, 0.5 ); + EXPECT_DOUBLE_EQ( 1.0, res ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, ValidIntervalLastBin ) +{ + std::vector x = { 0.0, 1.0, 100.0, 1100.0 }; + std::vector y = { 0.0, 2.0, 0.0, 2000.0 }; + + double res = RiaInterpolationTools::linear( x, y, 600.0 ); + EXPECT_DOUBLE_EQ( 1000.0, res ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, ValidIntervalValueTooLow ) +{ + std::vector x = { 0.0, 1.0 }; + std::vector y = { 0.0, 2.0 }; + + // Outside interval on low side + double res = RiaInterpolationTools::linear( x, y, -1.0 ); + EXPECT_DOUBLE_EQ( std::numeric_limits::infinity(), res ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaInterpolationToolsTest, ValidIntervalValueTooHigh ) +{ + std::vector x = { 0.0, 1.0 }; + std::vector y = { 0.0, 2.0 }; + + // Outside interval on high side + double res = RiaInterpolationTools::linear( x, y, 100.0 ); + EXPECT_DOUBLE_EQ( std::numeric_limits::infinity(), res ); +}