Quantcast
Channel: Intel® oneAPI Math Kernel Library & Intel® Math Kernel Library
Viewing all articles
Browse latest Browse all 2652

Data Fitting Functions - dfdInterpolateEx1d troubles

$
0
0

Hi,

I am trying to use dfdInterpolateEx1d to approximate a function by a linear interpolation and i get some troubles.

The function dfdInterpolateEx1d seems to be unable to do the interpolation if the site value is equal to the latest breakpoint.

There is my code:

int linear_extrap_func( MKL_INT* n, MKL_INT cell[], const double site[], double r[], void *params )
{
  double *ordinateRef = (double*)params;
  for(MKL_INT i=0; i<*n; i++) r[i] = *ordinateRef;
  return 0;
}

void LinearInterpolation( double*Z,
						  const double* X,
						  const int lenghtX,
						  const double* ordinateRef,
						  const int lenghtOrdinateRef,
						  const double minAbscissaRef,
						  const double maxAbscissaRef)
{
    DFTaskPtr task;                     // Data Fitting task descriptor
    MKL_INT nx;                         // number of break points
    MKL_INT xhint;                      // additional info about break points
    MKL_INT ny;                         // number of functions
    MKL_INT yhint;                      // additional info about function

    MKL_INT nsite;                      // total number of interpolation sites
    MKL_INT sitehint;                   // additional info about interpolation

    MKL_INT ndorder;                    // size of array describing derivative
                                        // orders
    MKL_INT dorder[] = { 1 };           // only value to calculate
                                        // will be computed
    MKL_INT rhint;                      // interpolation results storage format

    MKL_INT stype, sorder;

    double *datahint;                   // additional info about structure
                                        // of arrays x and y
    double *scoeff;

    int errcode = 0;
    int errnums = 0;

    sorder = DF_PP_LINEAR;
    stype  = DF_PP_DEFAULT;

    datahint = 0;

    double x_ref[2];
    nx        = lenghtOrdinateRef;
    xhint     = DF_UNIFORM_PARTITION;
    x_ref[0]  = minAbscissaRef;
    x_ref[1]  = maxAbscissaRef;

    scoeff = new double[DF_PP_LINEAR*(nx-1)];

    ny          = 1;
    yhint       = DF_MATRIX_STORAGE_ROWS;

    datahint	= NULL;

    nsite		= lenghtX;
    sitehint	= DF_NON_UNIFORM_PARTITION;

    ndorder		= 1;

    rhint		= DF_MATRIX_STORAGE_ROWS;

    errcode		= dfdNewTask1D( &task, nx, x_ref, xhint, ny, ordinateRef, yhint );

    errcode		= dfdEditPPSpline1D( task, sorder, stype, DF_NO_BC, 0, DF_NO_IC, 0, scoeff, DF_NO_HINT );

    errcode		= dfdConstruct1D( task, DF_PP_SPLINE, DF_METHOD_STD );

    dfdInterpCallBack extraFunc;
    extraFunc 	= reinterpret_cast<dfdInterpCallBack> (linear_extrap_func);

    /*errcode = dfdInterpolate1D( task, DF_INTERP, DF_METHOD_PP,
                                    nsite, X, sitehint, ndorder,
                                    dorder, datahint, Z, rhint, NULL);*/
     errcode 	= dfdInterpolateEx1D(	task, DF_INTERP, DF_METHOD_PP,
										nsite, X, sitehint, ndorder,
										dorder, datahint, Z, rhint, 0,
										extraFunc, &ordinateRef[0], extraFunc, &ordinateRef[lenghtOrdinateRef-1],
										0, 0, 0, 0);

    errcode = dfDeleteTask( &task );

    delete [] scoeff;
}

int main()
{
    const int lenghtX = 10;

    const double minAbscissaRef = 12.0;
    const double maxAbscissaRef = 28.0;
    const int lenghtOrdinateRef = 250;

    // output
    double *Z = new double[lenghtX];

    //ref values
    double *ordinateRef = new double[lenghtOrdinateRef];
    for (int i = 0; i < lenghtOrdinateRef; i++)
		ordinateRef[i] = i * 1.5 + 0.5 * M_PI;

	//y = a*x+b
    double a = (ordinateRef[lenghtOrdinateRef - 1] - ordinateRef[0]) / (maxAbscissaRef - minAbscissaRef);
    double b = ordinateRef[0] - minAbscissaRef * a;

    //Init X values
    double *X = new double[lenghtX];
    const double X_incr = (maxAbscissaRef - minAbscissaRef) / (lenghtX - 3);
    for (int i = 0; i < lenghtX; i++)
		X[i] = minAbscissaRef + (i - 1) * X_incr;

    LinearInterpolation( Z, X, lenghtX, ordinateRef, lenghtOrdinateRef, minAbscissaRef, maxAbscissaRef);

    for (int i = 0; i < lenghtX; ++i)
    {
        double expected = std::min( std::max(X[i]*a+b, ordinateRef[0]), ordinateRef[lenghtOrdinateRef - 1]);
        printf("%d %f %f %f",i, X[i], expected, Z[i]);
    }

    delete [] X;
    delete [] Z;
    delete [] ordinateRef;

	return 0;
}

and the output:

i	X[i]				expected			result
0 	9.71428571428572	1.5707963267949 	1.5707963267949
1 	12 					1.5707963267949		1.5707963267949
2 	14.2857142857143	54.9279391839377 	54.9279391839377
3 	16.5714285714286	108.285082041081 	108.285082041081
4 	18.8571428571429	161.642224898223 	161.642224898223
5 	21.1428571428571	214.999367755366 	214.999367755366
6 	23.4285714285714	268.356510612509 	268.356510612509
7 	25.7142857142857	321.713653469652 	321.713653469652
8 	28					375.070796326795 	4.01711400191502E-270
9 	30.2857142857143 	375.070796326795 	375.070796326795

The 9th result (when i=8, site = 28. = latest breakpoint) is a kind of NaN (4.017..E-270).

I guess that I did a mistake with the boundary condition or maybe in the extrapolation function...

Can someone help me ?

PS: The simple dfdInterpolate1D function works well, but I would like to use my own extrapolation function.

Thanks in advance for your help.


Viewing all articles
Browse latest Browse all 2652

Trending Articles