point_collocation

odl.discr.discr_utils.point_collocation(func, points, out=None, **kwargs)[source]

Sample a function on a grid of points.

This function represents the simplest way of discretizing a function. It does little more than calling the function on a single point or a set of points, and returning the result.

Parameters:
funccallable

Function to be sampled. It is expected to work with single points, meshgrids and point arrays, and to support an optional out argument. Usually, func is the return value of make_func_for_sampling.

pointspoint, meshgrid or array of points

The point(s) where to sample.

outnumpy.ndarray, optional

Array to which the result should be written.

kwargs

Additional arguments that are passed on to func.

Returns:
outnumpy.ndarray

Array holding the values of func at points. If out was given, the returned object is a reference to it.

See also

make_func_for_sampling

wrap a function

odl.discr.grid.RectGrid.meshgrid
numpy.meshgrid

Notes

This function expects its input functions to be written in a vectorization-conforming manner to ensure fast evaluation. See the ODL vectorization guide for a detailed introduction.

References

Examples

Sample a 1D function:

>>> from odl.discr.grid import sparse_meshgrid
>>> domain = odl.IntervalProd(0, 5)
>>> func = sampling_function(lambda x: x ** 2, domain)
>>> mesh = sparse_meshgrid([1, 2, 3])
>>> point_collocation(func, mesh)
array([ 1.,  4.,  9.])

By default, inputs are checked against domain to be in bounds. This can be switched off by passing bounds_check=False:

>>> mesh = sparse_meshgrid([-1, 0, 4])
>>> point_collocation(func, mesh, bounds_check=False)
array([  1.,   0.,  16.])

In two or more dimensions, the function to be sampled can be written as if its arguments were the components of a point, and an implicit loop around the call would iterate over all points:

>>> domain = odl.IntervalProd([0, 0], [5, 5])
>>> xs = [1, 2]
>>> ys = [3, 4, 5]
>>> mesh = sparse_meshgrid(xs, ys)
>>> func = sampling_function(lambda x: x[0] - x[1], domain)
>>> point_collocation(func, mesh)
array([[-2., -3., -4.],
       [-1., -2., -3.]])

It is possible to return results that require broadcasting, and to use optional function parameters:

>>> def f(x, c=0):
...     return x[0] + c
>>> func = sampling_function(f, domain)
>>> point_collocation(func, mesh)  # uses default c=0
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.]])
>>> point_collocation(func, mesh, c=2)
array([[ 3.,  3.,  3.],
       [ 4.,  4.,  4.]])

The point_collocation function also supports vector- and tensor-valued functions. They can be given either as a single function returning an array-like of results, or as an array-like of member functions:

>>> domain = odl.IntervalProd([0, 0], [5, 5])
>>> xs = [1, 2]
>>> ys = [3, 4]
>>> mesh = sparse_meshgrid(xs, ys)
>>> def vec_valued(x):
...     return (x[0] - 1., 0., x[0] + x[1])  # broadcasting
>>> # For a function with several output components, we must specify the
>>> # shape explicitly in the `out_dtype` parameter
>>> func1 = sampling_function(
...     vec_valued, domain, out_dtype=(float, (3,))
... )
>>> point_collocation(func1, mesh)
array([[[ 0.,  0.],
        [ 1.,  1.]],

       [[ 0.,  0.],
        [ 0.,  0.]],

       [[ 4.,  5.],
        [ 5.,  6.]]])
>>> list_of_funcs = [  # equivalent to `vec_valued`
...     lambda x: x[0] - 1,
...     0,                   # constants are allowed
...     lambda x: x[0] + x[1]
... ]
>>> # For an array of functions, the output shape can be inferred
>>> func2 = sampling_function(list_of_funcs, domain)
>>> point_collocation(func2, mesh)
array([[[ 0.,  0.],
        [ 1.,  1.]],

       [[ 0.,  0.],
        [ 0.,  0.]],

       [[ 4.,  5.],
        [ 5.,  6.]]])