Reputation: 11
I am using the latest release of dolfinx-fenics (https://fenicsproject.org) on a Lenovo Think Pad with an Intel(R) Core(TM) i7-8550U CPU @1.80GHZ. It's a 64-Bit-System with Windows 11 Pro version 23H2. I have an Intel(R) UHD Graphics 620 graphic card.
On it I have installed the latest version of Visual Studio Code and connect it via WSL 2 to my Ubuntu 22.04.4 installation. The Kernel I use is the one of Ubuntu with a python 3.10.12 To run FEM calculations with fenicsx I use a ipynb notebook, but the same error occurs using a .py standard file. I have below a code snippet (I try to make it minimal working)
from mpi4py import MPI
import pyvista
from dolfinx import mesh, plot
pyvista.OFF_SCREEN = True
print(pyvista.global_theme.jupyter_backend)
domain = mesh.create_unit_square(MPI.COMM_WORLD, 8, 8, mesh.CellType.quadrilateral)
tdim = domain.topology.dim
pyvista.start_xvfb()
domain.topology.create_connectivity(tdim, tdim)
topology, cell_types, geometry = plot.vtk_mesh(domain, tdim)
grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
plotter.show()
The result is a black image with nothing on it. I can try to plot a function instead but the results is that I see the colorbar with the labels but nothing more.
I have already tried a number of things.
pyvista.OFF_SCREEN = True
did not resolve the issue.plotter.disable_anti_aliasing()
did only make the picture to appear in white but not black anymore. No other changes.It is to note that I tried also simple examples from pyvista directly, getting the same issue.
You can try the same on the exact same settup using simply:
import pyvista as pv
from pyvista import examples
dataset = examples.download_st_helens()
plotter = pv.Plotter()
plotter.add_mesh(dataset)
plotter.show(jupyter_backend='static')
On two occasion I could get it to work but always after a restart of the kernel (without any other changes), the issue re-appeared.
UPDATE:
I could make the display in Visual studio work by simply using the 'html' jupyter backend. See the adapted code below.
import pyvista as pv
from pyvista import examples
pyvista.set_jupyter_backend('html')
dataset = examples.download_st_helens()
plotter = pv.Plotter()
plotter.add_mesh(dataset)
plotter.show()
However, I am facing the problem that I cannot export the image. E.g. I would want to make an export of the figure using
plotter.screenshot("filename.png")
This unfortunately gives mee the original issue with an all black image file.
I would appreciate any help on the export.
Upvotes: 1
Views: 763
Reputation: 1
I ran into the exact same problem as you with a pretty similar setup and it seems that I found a workaround (up to more testing). I do not really understand why/how it works so i do a mere "recipe" for my setup.
Most likely you are aware of the installation guide for pyvista, if not have a look at
https://docs.pyvista.org/getting-started/installation
and there the section "Running on WSL". They give a nice description of what to do to for interactive plotting in WSL(2). If you already installed mini/anaconda it boils down to (READ FURTHER)
conda activate vtk_env
conda install nodejs # required when importing pyvista in Jupyter
pip install jupyter pyvista[jupyter] trame
# To avoid "ModuleNotFoundError: No module named 'vtkOpenGLKitPython' "
# when importing vtk
# https://stackoverflow.com/q/32389599
# https://askubuntu.com/q/629692
sudo apt update && sudo apt install python-qt4 libgl1-mesa-glx
Now for the "recipe", in my system (x64)
I did the following installations in the fenicsx environment:
sudo apt update
sudo apt-get install libgl1-mesa-glx libegl1-mesa libxrandr2 libxrandr2 libxss1 libxcursor1 libxcomposite1 libasound2 libxi6 libxtst6
sudo install python-qt4
by pip install pyqt5
conda install notebook ipykernel
python3 -m ipykernel install --user --name=fenicsx-env
conda install -c conda-forge pyvista jupyterlab trame trame-vuetify trame-vtk ipywidgets
export DISPLAY=:99.0
export PYVISTA_OFF_SCREEN=true
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
sleep 1
to your .bashrc file
Some comments:
python3 -m ipykernel install --user --name=fenicsx-env
makes the conda environment accessible from JupyterLab.With this setup i can for example use
import pyvista as pv
sphere = pv.Sphere()
pl = pv.Plotter()
pl.add_mesh(sphere, show_edges=True)
pl.show()
to produce the sphere or in our use-cases of FEM you can use the code from the poisson example in fenicsx
from mpi4py import MPI
from dolfinx import mesh
domain = mesh.create_unit_square(MPI.COMM_WORLD, 8, 8, mesh.CellType.quadrilateral)
from dolfinx.fem import functionspace
V = functionspace(domain, ("Lagrange", 1))
from dolfinx import fem
uD = fem.Function(V)
uD.interpolate(lambda x: 1 + x[0]**2 + 2 * x[1]**2)
import numpy
# Create facet to cell connectivity required to determine boundary facets
tdim = domain.topology.dim
fdim = tdim - 1
domain.topology.create_connectivity(fdim, tdim)
boundary_facets = mesh.exterior_facet_indices(domain.topology)
boundary_dofs = fem.locate_dofs_topological(V, fdim, boundary_facets)
bc = fem.dirichletbc(uD, boundary_dofs)
import ufl
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
from dolfinx import default_scalar_type
f = fem.Constant(domain, default_scalar_type(-6))
a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx
L = f * v * ufl.dx
from dolfinx.fem.petsc import LinearProblem
problem = LinearProblem(a, L, bcs=[bc], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()
V2 = fem.functionspace(domain, ("Lagrange", 2))
uex = fem.Function(V2)
uex.interpolate(lambda x: 1 + x[0]**2 + 2 * x[1]**2)
L2_error = fem.form(ufl.inner(uh - uex, uh - uex) * ufl.dx)
error_local = fem.assemble_scalar(L2_error)
error_L2 = numpy.sqrt(domain.comm.allreduce(error_local, op=MPI.SUM))
error_max = numpy.max(numpy.abs(uD.x.array-uh.x.array))
# Only print the error on one process
if domain.comm.rank == 0:
print(f"Error_L2 : {error_L2:.2e}")
print(f"Error_max : {error_max:.2e}")
from dolfinx import plot
domain.topology.create_connectivity(tdim, tdim)
topology, cell_types, geometry = plot.vtk_mesh(domain, tdim)
grid = pv.UnstructuredGrid(topology, cell_types, geometry)
plotter = pv.Plotter()
plotter.add_mesh(grid, show_edges=True)
and
plotter.view_xy()
plotter.show()
to produce the mesh used in the FEM.
I hope this helps. If not hit me with further questions or your own considerations.
Caveat: This is my first answer on such a forum ever. So please dear stackoverflow community show some mercy. I would have commented first, but I do not have the necessary reputation. Also in these software things, I am completely self-taught so I often lack the fundamental understanding and fiddle around until it works. But of course I am looking forward to your feedback!
Upvotes: 0