NcmSplineFunc

NcmSplineFunc — Automatic generation of the knots for a spline.

Stability Level

Stable, unless otherwise indicated

Functions

Types and Values

Object Hierarchy

    GEnum
    ╰── NcmSplineFuncType

Includes

#include <numcosmo/math/ncm_spline_func.h>

Description

This function implements 4 different methods to automatically determine the NcmVector of knots, $\mathbf{x}$, of a NcmSpline given a relative error between the function $f$ to be interpolated and the spline result $\hat{f}$.

All available methods start with $n_0$ knots, $\mathbf{x}_0$, distributed across [xi , xf ], including both limiting points. The value of $n_0$ depends on the chosen interpolation method given by s , e.g., NcmSplineCubicNotaknot has $n_0 = 6$.

The function $f$ is first interpolated at the $\mathbf{x}_0$ knots, producing the interpolated function $\hat{f}_0$. Next, the existing $n_0 - 1$ bins, $\Delta \mathbf{x}_0 = \mathbf{x}_0^{i+1} - \mathbf{x}_0^{i}$, are divided in half and test points are placed at those positions, $\overline{\mathbf{x}}_0 = \frac{\mathbf{x}_0^{i+1} + \mathbf{x}_0^{i}}{2}$. The following tests are done for each one of the bins $\Delta \mathbf{x}_0$ separately: \begin{equation*} \left| \frac{ \hat{f}_0(\overline{\mathbf{x}}_0) - f(\overline{\mathbf{x}}_0)}{f(\overline{\mathbf{x}}_0)} \right| < \mathrm{rel \_ error} \end{equation*} and \begin{equation*} \left| \frac{ \int_{\Delta \mathbf{x}_0} \hat{f}_0 - \int_{\Delta \mathbf{x}_0} f }{ \int_{\Delta \mathbf{x}_0} f } \right| < \mathrm{rel \_ error}. \end{equation*} Where $\int_{\Delta \mathbf{x}_0} f$ is the integral of the input function $f$ evaluated using Simpson's rule \begin{equation*} \int_{\Delta \mathbf{x}_0} f = \frac{\Delta \mathbf{x}_0}{6} \left[ f \left( \mathbf{x}_0^{i} \right) + 4 f \left( \overline{\mathbf{x}}_0 \right) + f \left( \mathbf{x}_0^{i+1} \right) \right] \end{equation*}

and the interpolated function $\hat{f}_0$ is integrated by applying ncm_spline_eval_integ(). If any bin passes those relations then, its associated test point $\overline{\mathbf{x}}_0$ together with both knots, are defined as a good representation of the function $f$ and this specific bin does not need to be refined anymore. If not, then $\mathbf{x}_0 \cup \overline{\mathbf{x}}_0$ is splitted once again into two more symmetric test points around $\overline{\mathbf{x}}_0$. A new set of knots is defined, $\mathbf{x}_1 = \mathbf{x}_0 \cup \overline{\mathbf{x}}_0$. The ones which did not pass the tests define another set of test points $\overline{\mathbf{x}}_1$ that lie between the $\mathbf{x}_0\cup \overline{\mathbf{x}}_0$. The new set of knots $\mathbf{x}_1$ are used to create a new interpolated function $\hat{f}_1$, always in the full range [xi , xf ]. The same tests are performed as before, but now with $\hat{f}_1(\overline{\mathbf{x}}_1)$, $f(\overline{\mathbf{x}}_1)$ and the integral now has limits $\Delta \mathbf{x}_1 = \Delta \mathbf{x}_0/2$, but only for those bins that did not pass the previous test. Therefore, the tests are always applied on three knots at a time. This procedure is repeated until the desired accuracy is met across the whole range [xi , xf ]. Note that it will most probably create a inhomogeneous set of knots.

The figure shows a schematically evolution of the methodology for choosing the knots. It starts with 6 knots, $\mathbf{x}_0$ (black filled circles in the first line), used to create the interpolated function $\hat{f}_0$. The $\overline{\mathbf{x}}_0$ test points are created (blue squares in the second line) and the first tests are performed in each one of the five bins. In this example, only the first and the fourth bins did not pass both tests. One new set of knots is created, $\mathbf{x}_1 = \mathbf{x}_0 \cup \overline{\mathbf{x}}_0$ (second line) and their new test points, $\overline{\mathbf{x}}_1$ (red diamonds in the third line). Note that $\overline{\mathbf{x}}_1$ are only placed in the middle of the previously bins that did not pass the tests. The tests are done 4 times, one for each bin with a red diamond at it center, with width $\Delta \mathbf{x}_1 = \Delta \mathbf{x}_0/2$. Again, only two of them passed the tests. One new set of knots is created $\mathbf{x}_2 = \mathbf{x}_1 \cup \overline{\mathbf{x}}_1$ (third line) and their new test points, $\overline{\mathbf{x}}_2$ (black vertical ticks in the fourth line). The tests are done 4 times more, one for each bin with a black vertical tick at it center, with width $\Delta \mathbf{x}_2 = \Delta \mathbf{x}_1/2$. In this schematic example, the final set of knots is given by the last line $\mathbf{x} = \mathbf{x}_3 = \mathbf{x}_2 \cup \overline{\mathbf{x}}_2$, with 19 knots in total, also showing that the final distribution is not homogeneous. It is important to note that in all steps the interpolated function is created with all its knots: $\mathbf{x}_0 \rightarrow \hat{f}_0$, $\mathbf{x}_1 \rightarrow \hat{f}_1$, $\mathbf{x}_2 \rightarrow \hat{f}_2$, $\mathbf{x}_3 \rightarrow \hat{f}_3$. It is also worth noting that, in the description and example above, it was assumed a linear distribution of knots in each step, but there are other options listed at NcmSplineFuncType.

Functions

NcmSplineFuncF ()

gdouble
(*NcmSplineFuncF) (gdouble x,
                   GObject *obj);

ncm_spline_set_func ()

void
ncm_spline_set_func (NcmSpline *s,
                     NcmSplineFuncType ftype,
                     gsl_function *F,
                     const gdouble xi,
                     const gdouble xf,
                     gsize max_nodes,
                     const gdouble rel_error);

This function automatically determines the knots of s in the interval [xi , xf ] given a ftype and rel_error .

[skip]

Parameters

s

a NcmSpline

 

ftype

a NcmSplineFuncType

 

F

function to be approximated by spline functions

 

xi

lower knot

 

xf

upper knot

 

max_nodes

maximum number of knots

 

rel_error

relative error between the function to be interpolated and the spline result

 

ncm_spline_set_func_scale ()

void
ncm_spline_set_func_scale (NcmSpline *s,
                           NcmSplineFuncType ftype,
                           gsl_function *F,
                           const gdouble xi,
                           const gdouble xf,
                           gsize max_nodes,
                           const gdouble rel_error,
                           const gdouble scale,
                           gint refine,
                           gdouble refine_ns);

This function automatically determines the knots of s in the interval [xi , xf ] given a ftype and rel_error .

[skip]

Parameters

s

a NcmSpline

 

ftype

a NcmSplineFuncType

 

F

function to be approximated by spline functions

 

xi

lower knot

 

xf

upper knot

 

max_nodes

maximum number of knots

 

rel_error

relative error between the function to be interpolated and the spline result

 

scale

scale of function, it is used to compute the absolute tolerance abstol = f_scale * rel_error

 

refine

if TRUE sample additional points to check if there are regions not satisfying the required tolerance

 

refine_ns

number of standard-deviation used to refine the grid

 

ncm_spline_set_func1 ()

void
ncm_spline_set_func1 (NcmSpline *s,
                      NcmSplineFuncType ftype,
                      NcmSplineFuncF F,
                      GObject *obj,
                      gdouble xi,
                      gdouble xf,
                      gsize max_nodes,
                      gdouble rel_error);

This function automatically determines the knots of s in the interval [xi , xf ] given a ftype and rel_error .

Parameters

s

a NcmSpline.

 

ftype

a NcmSplineFuncType

 

F

function to be approximated by spline functions.

[scope call]

obj

GObject used by the function F .

[allow-none]

xi

lower knot

 

xf

upper knot

 

max_nodes

maximum number of knots

 

rel_error

relative error between the function to be interpolated and the spline result

 

ncm_spline_set_func_grid1 ()

void
ncm_spline_set_func_grid1 (NcmSpline *s,
                           NcmSplineFuncType ftype,
                           NcmSplineFuncF F,
                           GObject *obj,
                           gdouble xi,
                           gdouble xf,
                           gsize nnodes);

This function fills the spline s with the function F values in a uniform grid within the range [xi , xf ] and a total of nnodes knots.

The difference between ncm_spline_set_func_grid is how the user function is passed. Here, it uses a NcmSplineFuncF function and it parameters are allocated in the object obj . This function is more suitable to be used within Python.

Parameters

s

a NcmSpline.

 

ftype

a NcmSplineFuncType: must be either NCM_SPLINE_FUNC_GRID_LINEAR or NCM_SPLINE_FUNC_GRID_LOG

 

F

function to be interpolated.

[scope call]

obj

GObject used by the function F .

[allow-none]

xi

lower knot

 

xf

upper knot

 

nnodes

number of knots including both limits knots [xi , xf ]

 

ncm_spline_set_func_grid ()

void
ncm_spline_set_func_grid (NcmSpline *s,
                          NcmSplineFuncType ftype,
                          gsl_function *F,
                          const gdouble xi,
                          const gdouble xf,
                          gsize nnodes);

This function fills the spline s with the function F values in a uniform grid within the range [xi , xf ] and a total of nnodes knots.

[skip]

Parameters

s

a NcmSpline

 

ftype

a NcmSplineFuncType: must be either NCM_SPLINE_FUNC_GRID_LINEAR or NCM_SPLINE_FUNC_GRID_LOG

 

F

function to be interpolated

 

xi

lower knot

 

xf

upper knot

 

nnodes

number of knots including both limits knots [xi , xf ]

 

Types and Values

enum NcmSplineFuncType

Enumeration to choose which of the functions to be applied when interpolating the input gsl_function *F , $f$, with the desired rel_error in the range [xi , xf ]. The interpolation knots, $\mathbf{x}$, are automatically defined internally by the functions. For more details see description above.

Members

NCM_SPLINE_FUNCTION_4POINTS

FIXME

 

NCM_SPLINE_FUNCTION_SPLINE

The knots are evenly distributed on a linear base at each step. The test points are place at $\overline{\mathbf{x}} = \frac{\mathbf{x}^{i+1} + \mathbf{x}^{i}}{2}$.

 

NCM_SPLINE_FUNCTION_SPLINE_LNKNOT

The knots are evenly distributed on a logarithm base at each step. The test points are place at $\overline{\mathbf{x}} = \mathrm{exp}\left( \frac{\ln \mathbf{x}^{i+1} + \ln \mathbf{x}^{i}}{2} \right)$. This method is only applied for positive intervals and is indicated for functions that changes orders of magnitude across the interval.

 

NCM_SPLINE_FUNCTION_SPLINE_SINHKNOT

The knots are evenly distributed on a hyperbolic sine base at each step. The test points are place at $\overline{\mathbf{x}} = \sinh \left[ \frac{\sinh^{-1} \left( \mathbf{x}^{i+1} \right) + \sinh^{-1} \left( \mathbf{x}^{i} \right)}{2} \right]$. This method is indicated for functions that changes orders of magnitude across the interval.

 

NCM_SPLINE_FUNC_GRID_LINEAR

The knots are evenly distributed on a linear base in the entire range [xi , xf ].

 

NCM_SPLINE_FUNC_GRID_LOG

The knots are evenly distributed on a natural logarithmic base in the entire range [xi > 0, xf > xi > 0].

 

NCM_SPLINE_FUNC_DEFAULT_MAX_NODES

#define NCM_SPLINE_FUNC_DEFAULT_MAX_NODES 10000000

NCM_SPLINE_KNOT_DIFF_TOL

#define NCM_SPLINE_KNOT_DIFF_TOL (GSL_DBL_EPSILON * 1.0e2)