Evaluate a Function on a Grid#
import minterpy as mp
import numpy as np
Calling an instance of Grid
with a function or a Callable
evaluates
the given function on the unisolvent nodes and returns the corresponding
function values. In the context of polynomial interpolation, these function
values are the coefficients of a polynomial in the Lagrange basis.
This guide demonstrates how to call an instance of Grid
on a function.
Example: Function with one-dimensional output#
Consider the following problem:
Compute the formula
on the interpolation grid that corresponds to a complete multi-index set of polynomial degree \(3\) with respect to the \(l_p\)-degree \(2.0\).
Function to evaluate#
A valid function or callable that can be called with a Grid
instance
must satisfy the following:
it must accept as the first argument a two-dimensional array where each row corresponds to different evaluation points and each column corresponds to different spatial dimension.
it must return an array with the same length as the input.
The function or callable may accept additional arguments either positional or keyword.
The function as required above can be defined as follows:
def fun_one_dim(xx: np.ndarray) -> np.ndarray:
"""Compute the sum of squared."""
return np.sum(xx**2, axis=1)
Grid#
The interpolation grid that corresponds to the complete multi-index set
can be created using from_degree()
factory method:
spatial_dimension = 3
poly_degree = 3
lp_degree = 2.0
grd = mp.Grid.from_degree(spatial_dimension, poly_degree, lp_degree)
Function values on the grid#
By calling the Grid
instance on the function defined above, we evaluate
the function on the unisolvent nodes of the grid:
fun_values = grd(fun_one_dim)
fun_values
array([3. , 3. , 2.25, 2.25, 3. , 3. , 2.25, 2.25, 2.25, 1.5 , 2.25,
3. , 3. , 2.25, 3. , 3. , 2.25, 2.25, 2.25, 1.5 , 2.25, 2.25,
1.5 , 2.25, 2.25, 1.5 , 1.5 , 1.5 , 2.25])
As expected, these values are the same values from evaluating the given function on the unisolvent nodes:
fun_one_dim(grd.unisolvent_nodes)
array([3. , 3. , 2.25, 2.25, 3. , 3. , 2.25, 2.25, 2.25, 1.5 , 2.25,
3. , 3. , 2.25, 3. , 3. , 2.25, 2.25, 2.25, 1.5 , 2.25, 2.25,
1.5 , 2.25, 2.25, 1.5 , 1.5 , 1.5 , 2.25])
Example: Function with multi-dimensional output#
Consider the following problem:
Compute the formula
where
on the same interpolation grid as before.
Notice that the function now returns two outputs per input value.
The function or callable passed to the Grid
instance may also return
multiple outputs. The function must be defined such that it returns an array
whose each column corresponds to the different output.
The required function can therefore be defined as follows:
def fun_two_dim(xx: np.ndarray) -> np.ndarray:
"""Return the sum and product of squared."""
yy = np.empty((len(xx), 2))
yy[:, 0] = np.sum(xx**2, axis=1)
yy[:, 1] = np.prod(xx**2, axis=1)
return yy
The previous instance of Grid
can be directly used to obtain the values
of the multiple-output function:
grd(fun_two_dim)
array([[3. , 1. ],
[3. , 1. ],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[3. , 1. ],
[3. , 1. ],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[1.5 , 0.0625],
[2.25 , 0.25 ],
[3. , 1. ],
[3. , 1. ],
[2.25 , 0.25 ],
[3. , 1. ],
[3. , 1. ],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[1.5 , 0.0625],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[1.5 , 0.0625],
[2.25 , 0.25 ],
[2.25 , 0.25 ],
[1.5 , 0.0625],
[1.5 , 0.0625],
[1.5 , 0.0625],
[2.25 , 0.25 ]])
As expected, calling the Grid
instance with the function returns a two-dimensional
array whose each column corresponds to each outputs and each row corresponds to each unisolvent nodes.
Example: Function with additional arguments#
While the function passed to a Grid
instance must take as its first
argument a two-dimensional array, additional arguments may also be passed
to the function by passing positional and keyword arguments to the call.
For instance, suppose the function to be evaluated is defined as follows:
def fun_with_args(xx: np.ndarray, p: float) -> np.ndarray:
"""Return the row-wise lp-norm."""
return np.sum(np.abs(xx**p), axis=1)**(1/p)
To change the behavior of the function call via one of its argument
when the function is evaluated on the grid, pass the additional arguments
to the call to the Grid
instance.
For instance, with the additional argument to fun_with_args()
as a positional argument:
grd(fun_with_args, 1.0)
array([3. , 3. , 2.5, 2.5, 3. , 3. , 2.5, 2.5, 2.5, 2. , 2.5, 3. , 3. ,
2.5, 3. , 3. , 2.5, 2.5, 2.5, 2. , 2.5, 2.5, 2. , 2.5, 2.5, 2. ,
2. , 2. , 2.5])
grd(fun_with_args, 2.0)
array([1.73205081, 1.73205081, 1.5 , 1.5 , 1.73205081,
1.73205081, 1.5 , 1.5 , 1.5 , 1.22474487,
1.5 , 1.73205081, 1.73205081, 1.5 , 1.73205081,
1.73205081, 1.5 , 1.5 , 1.5 , 1.22474487,
1.5 , 1.5 , 1.22474487, 1.5 , 1.5 ,
1.22474487, 1.22474487, 1.22474487, 1.5 ])
…and as a keyword argument:
grd(fun_with_args, p=3.0)
array([1.44224957, 1.44224957, 1.2856408 , 1.2856408 , 1.44224957,
1.44224957, 1.2856408 , 1.2856408 , 1.2856408 , 1.07721735,
1.2856408 , 1.44224957, 1.44224957, 1.2856408 , 1.44224957,
1.44224957, 1.2856408 , 1.2856408 , 1.2856408 , 1.07721735,
1.2856408 , 1.2856408 , 1.07721735, 1.2856408 , 1.2856408 ,
1.07721735, 1.07721735, 1.07721735, 1.2856408 ])