Skip to content

Use new plotting API #58

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
container: dokken92/dolfinx_custom:07012022
container: dokken92/dolfinx_custom:21012022

env:
HDF5_MPI: "ON"
Expand Down Expand Up @@ -84,8 +84,7 @@ jobs:
- name: Build the book
run: |
PYVISTA_JUPYTER_BACKEND=static PYVISTA_OFF_SCREEN=false jupyter-book build -W .
# Add in -W once matplotlib is gone
# Pusb book to HTML to github pages
# Push book to HTML to github pages
- name: GitHub Pages action
uses: peaceiris/actions-gh-pages@v3.5.9
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ jobs:
run: echo ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
- name: Push to the DockerHub registry
run: |
docker push dokken92/dolfinx_custom:07012022
docker push dokken92/dolfinx_custom:21012022
5 changes: 4 additions & 1 deletion .github/workflows/main-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ jobs:
apt-get clean
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
pip3 install --no-cache-dir tqdm pandas seaborn
pip3 install notebook nbconvert jupyter-book myst_parser pyvista jupyterlab
pip3 install notebook nbconvert jupyter-book myst_parser pyvista jupyterlab jupyter
pip3 install ipygany pythreejs
pip3 install --no-cache-dir matplotlib setuptools --upgrade
jupyter nbextension enable --py --sys-prefix ipygany
rm -rf /usr/local/share/.cache/*
- name: Test building the book
run:
PYVISTA_JUPYTER_BACKEND=static PYVISTA_OFF_SCREEN=false jupyter-book build -W .
- name: Test notebooks in parallel
run: |
cd chapter1
Expand Down
4 changes: 3 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Changelog

## Dev
- All `pyvista` plotting has been rewritten to use `ipygany` and `pythreejs` as well as using a cleaner interface.
- `dolfinx.plot.create_vtk_topology` has been renamed to `dolfinx.plot.create_vtk_mesh` and can now be directly used as input to `pyvista.UnstructuredGrid`.
- `dolfinx.fem.Function.compute_point_values` has been deprecated. Interpolation into a CG-1 is now the way of getting vertex values.
- API updates wrt. DOLFINx. `Form`->`form`, `DirichletBC`->`dirichletbc`.
- Switch plotting backend to `ipygany` and `pythreejs`
- Updates on error computations in [Error control: Computing convergence rates](chapter4/convergence).
- Added tutorial on interpolation of `ufl.Expression` in [Deflection of a membrane](chapter1/membrane_code).
- Added tutorial on how to apply constant-valued Dirichet conditions in [Deflection of a membrane](chapter1/membrane_code).
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM dokken92/dolfinx_custom:07012022
FROM dokken92/dolfinx_custom:21012022

# create user with a home directory
ARG NB_USER
Expand Down
102 changes: 65 additions & 37 deletions chapter1/fundamentals_code.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@
"$ u = \\sum_{j=1}^N U_j\\phi_j.$\n",
"By writing `problem.solve()` we compute all the coefficients $U_1,\\dots, U_N$. These values are known as the _degrees of freedom_ (dofs). We can access the degrees of freedom by accessing the underlying vector in `uh`.\n",
"However, as a second order function space has more dofs than a linear function space, we cannot compare these arrays directly.\n",
"Therefore we compute the values of both `uex` and `uD` at the mesh nodes (for a linear mesh this is the vertices)."
"As we allready have interpolated the exact solution into the first order space when creating the boundary condition, we can compare the maximum values at any degree of freedom of the approximation space."
]
},
{
Expand All @@ -353,9 +353,7 @@
}
],
"source": [
"u_vertex_values = uh.compute_point_values()\n",
"u_ex_vertex_values = uex.compute_point_values()\n",
"error_max = numpy.max(numpy.abs(u_vertex_values - u_ex_vertex_values))\n",
"error_max = numpy.max(numpy.abs(uD.x.array-uh.x.array))\n",
"# Only print the error on one process\n",
"if mesh.comm.rank == 0:\n",
" print(f\"Error_L2 : {error_L2:.2e}\")\n",
Expand All @@ -366,10 +364,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Plotting the solution using pyvista\n",
"Once the solution has been computed, we will visualize it using [pyvista](https://docs.pyvista.org/), an interface to the VTK toolkit.\n",
"## Plotting the mesh using pyvista\n",
"We will visualizing the mesh using [pyvista](https://docs.pyvista.org/), an interface to the VTK toolkit.\n",
"We start by converting the mesh to a format that can be used with `pyvista`.\n",
"To do this we use the function `dolfinx.plot.create_vtk_topology`. The first step is to create an unstructured grid that can be used by `pyvista`."
"To do this we use the function `dolfinx.plot.create_vtk_mesh`. The first step is to create an unstructured grid that can be used by `pyvista`."
]
},
{
Expand All @@ -378,8 +376,10 @@
"metadata": {},
"outputs": [],
"source": [
"from dolfinx.plot import create_vtk_topology\n",
"topology, cell_types = create_vtk_topology(mesh, mesh.topology.dim)"
"from dolfinx.plot import create_vtk_mesh\n",
"import pyvista\n",
"topology, cell_types, geometry = create_vtk_mesh(mesh, mesh.topology.dim)\n",
"grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)"
]
},
{
Expand All @@ -395,46 +395,81 @@
"metadata": {},
"outputs": [],
"source": [
"import pyvista\n",
"pyvista.set_jupyter_backend(\"pythreejs\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start by creating a pyvista grid the `vtk_topology` and the `mesh.geometry`.\n",
"Next, we attach data from our solution `uh` by computing the values of the function at each vertex."
"We can now use the `pyvista.Plotter` to visualize the mesh. We visualize it by showing it in 2D and warped in 3D.\n",
"In the jupyter notebook environment, we use the default setting of `pyvista.OFF_SCREEN=False`, which will render plots directly in the notebook."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8153fbfcef014a3899925003792a4ba1",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Renderer(camera=PerspectiveCamera(aspect=1.3333333333333333, children=(DirectionalLight(color='#fefefe', inten…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"grid = pyvista.UnstructuredGrid(topology, cell_types, mesh.geometry.x)\n",
"grid.point_data[\"u\"] = uh.compute_point_values().real\n",
"grid.set_active_scalars(\"u\")"
"plotter = pyvista.Plotter()\n",
"plotter.add_mesh(grid, show_edges=True)\n",
"plotter.view_xy()\n",
"if not pyvista.OFF_SCREEN:\n",
" plotter.show()\n",
"else:\n",
" pyvista.start_xvfb()\n",
" figure = plotter.screenshot(\"fundamentals_mesh.png\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now use the `pyvista.Plotter` to visualize the solution. We visualize it by showing it in 2D and warped in 3D.\n",
"In the jupyter notebook environment, we use the default setting of `pyvista.OFF_SCREEN=False`, which will render plots directly in the notebook."
"## Plotting a function using pyvista\n",
"We want to plot the solution `uh`. As the function space used to defined the mesh is disconnected from the function space defining the mesh, we create a mesh based on the dof coordinates for the function space `V`. We use `dolfinx.plot.create_vtk_mesh` with the function space as input to create a mesh with mesh geometry based on the dof coordinates."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"u_topology, u_cell_types, u_geometry = create_vtk_mesh(V)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we create the `pyvista.UnstructuredGrid` and add the dof-values to the mesh."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "026dd4bdc8354af88ecd23be302ee96c",
"model_id": "54e3bc7b8f764a31836e14906e188aff",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -447,14 +482,14 @@
}
],
"source": [
"plotter = pyvista.Plotter()\n",
"plotter.add_mesh(grid, show_edges=True)\n",
"plotter.view_xy()\n",
"u_grid = pyvista.UnstructuredGrid(u_topology, u_cell_types, u_geometry)\n",
"u_grid.point_data[\"u\"] = uh.x.array.real\n",
"u_grid.set_active_scalars(\"u\")\n",
"u_plotter = pyvista.Plotter()\n",
"u_plotter.add_mesh(u_grid, show_edges=True)\n",
"u_plotter.view_xy()\n",
"if not pyvista.OFF_SCREEN:\n",
" plotter.show()\n",
"else:\n",
" pyvista.start_xvfb()\n",
" figure = plotter.screenshot(\"fundamentals.png\")"
" u_plotter.show()"
]
},
{
Expand All @@ -467,13 +502,13 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2b14ac59f2cf4d129b2843ce038c4b90",
"model_id": "c03cdb732aa94579ab795f0188ce9572",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -487,7 +522,7 @@
],
"source": [
"if not pyvista.OFF_SCREEN:\n",
" warped = grid.warp_by_scalar()\n",
" warped = u_grid.warp_by_scalar()\n",
" plotter2 = pyvista.Plotter()\n",
" plotter2.add_mesh(warped, show_edges=True, show_scalar_bar=True)\n",
" plotter2.show(jupyter_backend=\"ipygany\")"
Expand All @@ -503,7 +538,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -523,13 +558,6 @@
" :filter: cited and ({\"chapter1/fundamentals_code\"} >= docnames)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
Loading