# Render function with pyvista during parallel execution

**URL:** <https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003>\
**Category:** I/O\
**Created:** [December 19, 2022, 11:37am UTC](https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003 "2022-12-19T11:37:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![leonh](https://avatars.discourse-cdn.com/v4/letter/l/919ad9/32.png) [@leonh](https://fenicsproject.discourse.group/u/leonh)\
**Post date:** [December 19, 2022, 11:37am UTC](https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003/1 "2022-12-19T11:37:59Z")

</div>

Simulations can take a long time, and I’d like to see if the results are heading in the right direction without waiting for it to finish. This is why I’d like to render the current state using pyvista every n simulation steps. However, I’m having trouble getting this to work with MPI.

Consider the following minimal example:

```auto
from mpi4py import MPI
from dolfinx import *

comm = MPI.COMM_WORLD
nx = 20

msh = mesh.create_rectangle(comm, points=((-1.5, -1.0), (1.5, 1.0)), n=(nx, nx), cell_type=mesh.CellType.triangle)

V = fem.FunctionSpace(msh, ("CG", 1))

uh = fem.Function(V)
uh.interpolate(lambda x: x[0]+x[1])

if comm.rank == 0:
    try:
        import pyvista
        cells, types, x = plot.create_vtk_mesh(msh)
        grid = pyvista.UnstructuredGrid(cells, types, x)
        grid.point_data["u"] = uh.x.array.real
        grid.set_active_scalars("u")
        plotter = pyvista.Plotter()
        plotter.add_mesh(grid, show_edges=True)
        plotter.show()
    except ModuleNotFoundError:
        print("'pyvista' is required to visualise the solution")
        print("Install 'pyvista' with pip: 'python3 -m pip install pyvista'")

```

Running this without MPI or with `mpirun -n 1` gives:

 ![mesh](https://global.discourse-cdn.com/free1/uploads/fenicsproject1/original/2X/3/33ae97c4381d89d56f30935ec701a648e3803f07.png)

However, when I run the code with `mpirun -n 4`:

 ![Teilmesh](https://global.discourse-cdn.com/free1/uploads/fenicsproject1/original/2X/7/7cd1d1bb113385a61a6366d3176d6f49e9a1e7e5.png)

Only the subdomain of rank 0 gets rendered, which shouldn’t be a surprise. But how can I fix this? What’s the easiest way to piece together the function from all rank’s subdomains?

---

<div class="post-metadata">

**Author:** ![dokken](https://yyz2.discourse-cdn.com/free1/user_avatar/fenicsproject.discourse.group/dokken/32/1560_2.png) [@dokken](https://fenicsproject.discourse.group/u/dokken)\
**Post date:** [December 19, 2022, 12:21pm UTC](https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003/2 "2022-12-19T12:21:56Z")

</div>

You would need to gather the mesh data produced by

> [@leonh](#):
>
> `cells, types, x = plot.create_vtk_mesh(msh)`

on the first process, and similarly for the `uh.x.array`, it has to be garhered on rank 0.

---

<div class="post-metadata">

**Author:** ![leonh](https://avatars.discourse-cdn.com/v4/letter/l/919ad9/32.png) [@leonh](https://fenicsproject.discourse.group/u/leonh)\
**Post date:** [December 19, 2022, 2:01pm UTC](https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003/3 "2022-12-19T14:01:27Z")

</div>

Yes, thanks. But how exactly can I do that?  
I’ve gathered simple values before, such as the global maximum of a function:  
`comm.reduce(uh.vector.max()[1], MPI.MAX)`  
But I can’t figure out how to gather the function itself.

---

<div class="post-metadata">

**Author:** ![dokken](https://yyz2.discourse-cdn.com/free1/user_avatar/fenicsproject.discourse.group/dokken/32/1560_2.png) [@dokken](https://fenicsproject.discourse.group/u/dokken)\
**Post date:** [December 19, 2022, 2:09pm UTC](https://fenicsproject.discourse.group/t/render-function-with-pyvista-during-parallel-execution/10003/4 "2022-12-19T14:09:15Z")

</div>

I’ve for instance shown it here (using u.vector and not u.x.array): [Gather solutions in parallel in FEniCSX - #2 by dokken](https://fenicsproject.discourse.group/t/gather-solutions-in-parallel-in-fenicsx/5907/2)

In your case you should use u.x.array as you need the ghost dofs to properly render on each component of the mesh
