Plot Nédélec finite element function with vectors.
()
| 247 | |
| 248 | |
| 249 | def plot_nedelec(): |
| 250 | """Plot Nédélec finite element function with vectors.""" |
| 251 | msh = create_unit_cube( |
| 252 | MPI.COMM_WORLD, 4, 3, 5, cell_type=CellType.tetrahedron, dtype=np.float64 |
| 253 | ) |
| 254 | |
| 255 | # We create a pyvista plotter |
| 256 | plotter = pyvista.Plotter() |
| 257 | plotter.add_text( |
| 258 | "Mesh and corresponding vectors", position="upper_edge", font_size=14, color="black" |
| 259 | ) |
| 260 | |
| 261 | # Next, we create a pyvista.UnstructuredGrid based on the mesh |
| 262 | pyvista_cells, cell_types, x = plot.vtk_mesh(msh) |
| 263 | grid = pyvista.UnstructuredGrid(pyvista_cells, cell_types, x) |
| 264 | |
| 265 | # Add this grid (as a wireframe) to the plotter |
| 266 | plotter.add_mesh(grid, style="wireframe", line_width=2, color="black") |
| 267 | |
| 268 | # Create a function space consisting of first order Nédélec (first |
| 269 | # kind) elements and interpolate a vector-valued expression |
| 270 | V = functionspace(msh, ("N1curl", 2)) |
| 271 | u = Function(V, dtype=np.float64) |
| 272 | u.interpolate(lambda x: (x[2] ** 2, np.zeros(x.shape[1]), -x[0] * x[2])) |
| 273 | |
| 274 | # Exact visualisation of the Nédélec spaces requires a Lagrange or |
| 275 | # discontinuous Lagrange finite element functions. Therefore, we |
| 276 | # interpolate the Nédélec function into a first-order discontinuous |
| 277 | # Lagrange space. |
| 278 | gdim = msh.geometry.dim |
| 279 | V0 = functionspace(msh, ("Discontinuous Lagrange", 2, (gdim,))) |
| 280 | u0 = Function(V0, dtype=np.float64) |
| 281 | u0.interpolate(u) |
| 282 | |
| 283 | # Create a second grid, whose geometry and topology is based on the |
| 284 | # output function space |
| 285 | cells, cell_types, x = plot.vtk_mesh(V0) |
| 286 | grid = pyvista.UnstructuredGrid(cells, cell_types, x) |
| 287 | |
| 288 | # Create point cloud of vertices, and add the vertex values to the |
| 289 | # cloud |
| 290 | grid.point_data["u"] = u0.x.array.reshape(x.shape[0], V0.dofmap.index_map_bs) |
| 291 | glyphs = grid.glyph(orient="u", factor=0.1) |
| 292 | |
| 293 | # We add in the glyphs corresponding to the plotter |
| 294 | plotter.add_mesh(glyphs) |
| 295 | |
| 296 | # Save as png if we are using a container with no rendering |
| 297 | if pyvista.OFF_SCREEN: |
| 298 | plotter.screenshot( |
| 299 | out_folder / "3D_wireframe_with_vectors.png", |
| 300 | transparent_background=transparent, |
| 301 | window_size=[figsize, figsize], |
| 302 | ) |
| 303 | else: |
| 304 | plotter.show() |
| 305 | |
| 306 |
no test coverage detected