https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: 0d8e0cb0d00933663e03db3daee3172ca79d5d23 authored by Dmitry Yu. Naumov on 16 March 2021, 07:02:19 UTC
Merge branch 'ReplaceBoostAny' into 'master'
Tip revision: 0d8e0cb
TestPiecewiseLinearInterpolation.cpp
/**
 * \file
 * \author Thomas Fischer
 * \date Feb 12, 2013
 *
 * \copyright
 * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 */

// stl
#include <limits>

// google test
#include "gtest/gtest.h"

#include "MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h"

TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolation)
{
    const std::size_t size(1000);
    std::vector<double> supp_pnts;
    std::vector<double> values;
    for (std::size_t k(0); k < size; ++k)
    {
        supp_pnts.push_back(static_cast<double>(k));
        if (k % 2 == 0)
        {
            values.push_back(0.0);
        }
        else
        {
            values.push_back(1.0);
        }
    }

    MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
                                                        std::move(values)};
    // Interpolation
    for (std::size_t k(0); k < size - 1; ++k)
    {
        ASSERT_NEAR(0.5, interpolation.getValue(k + 0.5),
                    std::numeric_limits<double>::epsilon());
    }

    for (std::size_t k(0); k < size - 1; ++k)
    {
        if (k % 2 == 0)
        {
            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.25),
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.75),
                        std::numeric_limits<double>::epsilon());
        }
        else
        {
            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.25),
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.75),
                        std::numeric_limits<double>::epsilon());
        }
    }

    // Extrapolation
    ASSERT_NEAR(0.0, interpolation.getValue(-0.5),
                std::numeric_limits<double>::epsilon());
    // Extrapolation
    ASSERT_NEAR(1.0, interpolation.getValue(size - 0.5),
                std::numeric_limits<double>::epsilon());
}

TEST(MathLibInterpolationAlgorithms,
     PiecewiseLinearInterpolationSupportPntsInReverseOrder)
{
    const std::size_t size(1000);
    std::vector<double> supp_pnts;
    std::vector<double> values;
    for (std::size_t k(0); k < size; ++k)
    {
        supp_pnts.push_back(static_cast<double>(size - 1 - k));
        if (k % 2 == 0)
        {
            values.push_back(1.0);
        }
        else
        {
            values.push_back(0.0);
        }
    }

    MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
                                                        std::move(values)};
    // Interpolation
    for (std::size_t k(0); k < size - 1; ++k)
    {
        ASSERT_NEAR(0.5, interpolation.getValue(k + 0.5),
                    std::numeric_limits<double>::epsilon());
    }

    for (std::size_t k(0); k < size - 1; ++k)
    {
        if (k % 2 == 0)
        {
            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.25),
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.75),
                        std::numeric_limits<double>::epsilon());
        }
        else
        {
            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.25),
                        std::numeric_limits<double>::epsilon());
            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.75),
                        std::numeric_limits<double>::epsilon());
        }
    }

    // Extrapolation
    ASSERT_NEAR(0.0, interpolation.getValue(-0.5),
                std::numeric_limits<double>::epsilon());
    // Extrapolation
    ASSERT_NEAR(1.0, interpolation.getValue(size - 0.5),
                std::numeric_limits<double>::epsilon());
}

TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationDerivative)
{
    const std::size_t size(1000);
    std::vector<double> supp_pnts;
    std::vector<double> values;
    for (std::size_t k(0); k < size; ++k)
    {
        supp_pnts.push_back(static_cast<double>(k));
        values.push_back(static_cast<double>(k * k));
    }

    MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
                                                        std::move(values)};
    // Interpolation
    for (std::size_t k(0); k < size - 1; ++k)
    {
        ASSERT_NEAR(1 + 2 * static_cast<double>(k),
                    interpolation.getDerivative(k + 0.5),
                    std::numeric_limits<double>::epsilon());
    }
    //check, if a point is located between the first and second points
    //(or last and second to last point), the derivative is calculated
    //using linear interpolation.
    ASSERT_NEAR(2.6, interpolation.getDerivative(1.3),
        std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(1995, interpolation.getDerivative(997.3),
        std::numeric_limits<double>::epsilon());
    // max and min value test
    ASSERT_NEAR(1, interpolation.getDerivative(0),
                std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(1997, interpolation.getDerivative(999),
                std::numeric_limits<double>::epsilon());

    // Extrapolation
    ASSERT_NEAR(0, interpolation.getDerivative(-1),
                std::numeric_limits<double>::epsilon());
    // Extrapolation
    ASSERT_NEAR(0, interpolation.getDerivative(1001),
                std::numeric_limits<double>::epsilon());
}
back to top