Visualizing quadrature functions as point clouds#
Author: Henrik N.T. Finsberg
SPDX-License-Identifier: MIT
Quadrature functions are not possible to visualize directly in ParaView, as they are not defined on a mesh.
However, we can visualize them as point clouds.
In this example we will show how you can use scifem to save your quadrature fuctions as XDMF files,
which can be loaded into ParaView for visualization.
Note
This demo requires a backend for writing HDF5 files. Please install scifem with either scifem[adios2] or scifem[h5py].
First, we import the necessary modules.
# First initialize logging
logging.basicConfig(level=logging.INFO)
Now let’s create a quadrature function on a unit square mesh. We will use the basix.ufl module to create the quadrature element.
mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10, dolfinx.mesh.CellType.triangle, dtype=np.float64)
el = basix.ufl.quadrature_element(
scheme="default", degree=3, cell=mesh.basix_cell(), value_shape=()
)
V = dolfinx.fem.functionspace(mesh, el)
u = dolfinx.fem.Function(V)
u.interpolate(lambda x: np.sin(np.pi * x[0]) * np.sin(np.pi * x[1]))
One option that already exists with the current DOLFINx/Pyvista API is to plot them as points
import pyvista
plotter = pyvista.Plotter()
plotter.add_points(
V.tabulate_dof_coordinates(),
scalars=u.x.array,
render_points_as_spheres=True,
point_size=20,
show_scalar_bar=False,
)
if not pyvista.OFF_SCREEN:
plotter.show()
2026-08-24 20:16:53.500 ( 0.719s) [ 7F0B6BCD03C0]vtkXOpenGLRenderWindow.:1460 WARN| bad X server connection. DISPLAY=:99.0
INFO:trame_server.utils.namespace:Translator(prefix=None)
INFO:wslink.backends.aiohttp:awaiting runner setup
INFO:wslink.backends.aiohttp:awaiting site startup
INFO:wslink.backends.aiohttp:Print WSLINK_READY_MSG
INFO:wslink.backends.aiohttp:Schedule auto shutdown with timeout 0
INFO:wslink.backends.aiohttp:awaiting running future
Using scifem, we can write the point cloud data to an XDMFFile that can be opened with Paraview.
with scifem.xdmf.XDMFFile("point_cloud.xdmf", [u]) as xdmf:
xdmf.write(0.0)
/dolfinx-env/lib/python3.14/site-packages/scifem/xdmf.py:420: UserWarning: ADIOS2 not available, using h5py
warnings.warn(msg)
WARNING:root:ADIOS2 not available, using h5py
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[6], line 1
----> 1 with scifem.xdmf.XDMFFile("point_cloud.xdmf", [u]) as xdmf:
2 xdmf.write(0.0)
File /dolfinx-env/lib/python3.14/site-packages/scifem/xdmf.py:654, in XDMFFile.__init__(self, filename, functions, filemode, backend)
651 raise ValueError("All functions must be in the same function space")
652 self._data = data
--> 654 self._init_backend()
File /dolfinx-env/lib/python3.14/site-packages/scifem/xdmf.py:424, in BaseXDMFFile._init_backend(self)
422 self.backend = "h5py"
423 if self.backend == "h5py":
--> 424 self._init_h5py()
File /dolfinx-env/lib/python3.14/site-packages/scifem/xdmf.py:430, in BaseXDMFFile._init_h5py(self)
426 def _init_h5py(self) -> None:
427 logger.debug("Initializing h5py")
428 self._outfile = h5pyfile(
429 h5name=self.h5name, filemode=self.filemode, comm=self._data.comm
--> 430 ).__enter__()
431 self._step = self._outfile.create_group(np.bytes_("Step0"))
432 points = self._step.create_dataset(
433 "Points",
434 (self._data.num_dofs_global, self._data.points.shape[1]),
435 dtype=self._data.points.dtype,
436 )
File /usr/lib/python3.14/contextlib.py:141, in _GeneratorContextManager.__enter__(self)
139 del self.args, self.kwds, self.func
140 try:
--> 141 return next(self.gen)
142 except StopIteration:
143 raise RuntimeError("generator didn't yield") from None
File /dolfinx-env/lib/python3.14/site-packages/scifem/xdmf.py:148, in h5pyfile(h5name, filemode, force_serial, comm)
137 @contextlib.contextmanager
138 def h5pyfile(h5name, filemode="r", force_serial: bool = False, comm=None):
139 """Context manager for opening an HDF5 file with h5py.
140
141 Args:
(...) 146
147 """
--> 148 import h5py
150 if comm is None:
151 comm = MPI.COMM_WORLD
ModuleNotFoundError: No module named 'h5py'
The point cloud can now be loaded into ParaView for visualization, by selecting “Point Gaussian” as the representation.

We can write any dolfinx.fem.FunctionSpace that has support for tabulate_dof_coordinates to a point cloud.
For example, we can create a higher order Lagrange space, and write two functions to file.
Q = dolfinx.fem.functionspace(mesh, ("Lagrange", 3, (2, )))
q_1 = dolfinx.fem.Function(Q, name="q_sin")
q_1.interpolate(lambda x: (np.sin(np.pi * x[0]), np.sin(np.pi * x[1])))
q_2 = dolfinx.fem.Function(Q, name="q_cos")
q_2.interpolate(lambda x: (np.cos(np.pi * x[0]), np.cos(np.pi * x[1])))
We write these two functions to file as illustrated above
yielding the following point clouds in ParaView after applying glyphs.

If you have time dependent data, you can write multiple time steps to the same file using e.g
If you need to keep the file open for longer, you can use the following syntax