Point evaluation¶
Firedrake can evaluate Function
s at arbitrary physical
points. This feature can be useful for the evaluation of the result
of a simulation. Two APIs are offered to this feature: a
Firedrake-specific one, and one from UFL.
Firedrake API¶
Firedrake offers a convenient API for evaluating functions at
arbitrary points via at()
:
# evaluate f at a 1-dimensional point
f.at(0.3)
# evaluate f at two 1-dimensional points, or at one 2-dimensional point
# (depending on f's geometric dimension)
f.at(0.2, 0.4)
# evaluate f at one 2-dimensional point
f.at([0.2, 0.4])
# evaluate f at two 2-dimensional point
f.at([0.2, 0.4], [1.2, 0.5])
# evaluate f at two 2-dimensional point (same as above)
f.at([[0.2, 0.4], [1.2, 0.5]])
While in these examples we have only shown lists, other iterables
such as tuples and numpy
arrays are also accepted. The following
are equivalent:
f.at(0.2, 0.4)
f.at((0.2, 0.4))
f.at([0.2, 0.4])
f.at(numpy.array([0.2, 0.4]))
For a single point, the result is a numpy
array, or a tuple of
numpy
arrays in case of mixed functions. When evaluating
multiple points, the result is a list of values for each point.
To summarise:
Single point, non-mixed:
numpy
arraySingle point, mixed: tuple of
numpy
arraysMultiple points, non-mixed: list of
numpy
arraysMultiple points, mixed: list of tuples of
numpy
arrays
Points outside the domain¶
When any point is outside the domain of the function,
PointNotInDomainError
exception is raised. If
dont_raise=True
is passed to at()
, the result is
None
for those points which fall outside the domain.
mesh = UnitIntervalMesh(8)
f = mesh.coordinates
f.at(1.2) # raises exception
f.at(1.2, dont_raise=True) # returns None
f.at(0.5, 1.2) # raises exception
f.at(0.5, 1.2, dont_raise=True) # returns [0.5, None]
Warning
Point evaluation on immersed manifolds is not supported yet, due to the difficulty of specifying a physical point on the manifold.
Evaluation on a moving mesh¶
If you move the mesh, by changing the mesh coordinates, then the bounding box tree that Firedrake
maintains to ensure fast point evaluation must be rebuilt. To do
this, after moving the mesh, call
clear_spatial_index()
on the mesh you have just
moved.
Evaluation with a distributed mesh¶
There is limited support for point evaluation when running Firedrake in parallel. There is no special API, but there are some restrictions:
Point evaluation is a collective operation.
Each process must ask for the same list of points.
Each process will get the same values.
UFL API¶
UFL reserves the function call operator for evaluation:
f([0.2, 0.4])
will evaluate \(f\) at \((0.2, 0.4)\). UFL does not accept
multiple points at once, and cannot configure what to do with a point
which is not in the domain. The advantage of this syntax is that it
works on any Expr
, for example:
(f*sin(f)([0.2, 0.4])
will evaluate \(f \cdot \sin(f)\) at \((0.2, 0.4)\).
Note
The expression itself is not translated into C code. While the evaluation of a function uses the same infrastructure as the Firedrake API, which uses generated C code, the expression tree is evaluated by UFL in Python.