/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM 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.

    OpenFOAM 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
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "LinearInterpolator1D.H"

#include "error.H"
#include "Switch.H"


// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //


// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
bool Foam::LinearInterpolator1D::_checkSorted(const scalarField& grid)
{
    Switch sorted = true;

    for (label i = 1; i < srcGrid_.size(); i++)
    {
        if (grid[i-1] >= grid[i])
        {
            sorted = false;
            break;
        }
    }

    return sorted;
}


// * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //


// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::LinearInterpolator1D::LinearInterpolator1D()
{}


Foam::LinearInterpolator1D::LinearInterpolator1D(const scalarField& srcGrid, const scalarField& dstGrid)
:
    srcGrid_(srcGrid),
    dstGrid_(dstGrid),
    idxHigh_(dstGrid.size()),
    coef_(dstGrid.size())
{
    // Check dstGrid and srcGrid are intervals
    if (!(dstGrid_.first() < dstGrid_.last() && srcGrid_.first() < srcGrid_.last()))
    {
        FatalErrorInFunction
            << "Invalid grids"
            << abort(FatalError);
    }

    // Check dstGrid lies within srcGrid
    if (dstGrid_.first() < srcGrid_.first() || srcGrid_.last() < dstGrid_.last())
    {
        FatalErrorInFunction
            << "Extrapolation attempted"
            << abort(FatalError);
    }

    // Check srcGrid and dstGrid are sorted
    if (!(_checkSorted(dstGrid_) && _checkSorted(srcGrid_)))
    {
        FatalErrorInFunction
            << "Unsorted grids"
            << abort(FatalError);
    }

    forAll (dstGrid_, j)
    {
        for (label i = 1; i < srcGrid_.size(); i++)
        {
            if (srcGrid_[i] >= dstGrid_[j])
            {
                idxHigh_[j] = i;
                coef_[j] = (srcGrid_[i] - dstGrid_[j]) / (srcGrid_[i] - srcGrid_[i-1]);
                break;
            }
        }
    }
}


Foam::LinearInterpolator1D::LinearInterpolator1D(const LinearInterpolator1D&)
{}



// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::LinearInterpolator1D::~LinearInterpolator1D()
{}


// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //


void Foam::LinearInterpolator1D::interpolate(const scalarField& src, scalarField& dst)
{
    forAll (dst, i)
    {
        dst[i] = coef_[i]*src[idxHigh_[i]-1] + (1.0-coef_[i])*src[idxHigh_[i]];
    }

    return;
}


// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //

void Foam::LinearInterpolator1D::operator=(const LinearInterpolator1D& rhs)
{
    // Check for assignment to self
    if (this == &rhs)
    {
        FatalErrorInFunction
            << "Attempted assignment to self"
            << abort(FatalError);
    }
}

// * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * * //


// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //


// ************************************************************************* //
