Blog : Plotting Von Karman vortex street

Let’s imagine we need velocity contour plots in vector format (SVG, PDF).

Usually, we use Matplotlib for this purpose. It includes tricontourf function, which can even triangulate data. However, here we have a hole in the data (the cylinder) that should not be triangulated. Therefore, we use VTK output from cuttingPlane function object.

The plotting is split into data preparation and the plotting itself.

For data preparation, we use VTK Python module to read the data and triangulate it for compatibility with the Matplotlib. Then we extract the vertices, velocity values, and triangles, which are subsequently passed to the tricontourf function.

The Python code for the described procedure is shown below.

First, we import necessary modules:

#!/usr/bin/env python3

import vtk
from vtk.util import numpy_support

import numpy as np

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

First is VTK, which is used for reading and manipulating function object output. Then we import Numpy for fast array manipulations, and finally we import Matplotlib for plotting. make_axes_locatable is needed for the color bar.

reader = vtk.vtkXMLPolyDataReader()

reader.SetFileName('postProcessing/surfacesf/200/centerPlane.vtp')
reader.Update()

data = reader.GetOutput()

triangle_filter = vtk.vtkTriangleFilter()
triangle_filter.SetInputData(data)
triangle_filter.Update()
data = triangle_filter.GetOutput()

Next, we read and triangulate the velocity data.

vtk_points = data.GetPoints().GetData()
points = numpy_support.vtk_to_numpy(vtk_points)
x = points[:, 0]
y = points[:, 1]

vtk_vectors = data.GetPointData().GetArray("U")

vtk_cells = data.GetPolys().GetData()
cells_raw = numpy_support.vtk_to_numpy(vtk_cells)
triangles = cells_raw.reshape(-1, 4)[:, 1:]

U = numpy_support.vtk_to_numpy(vtk_vectors)
magU = np.linalg.norm(U, axis=1)

Then we extract VTK file vertices, cell velocity values, triangles, and calculate the velocity magnitude.

fig, ax = plt.subplots(figsize=(8, 6))

contour_filled = ax.tricontourf(x, y, triangles, magU, levels=16, cmap="turbo")

ax.tricontour(
    x, y, triangles, magU, levels=16, colors="white", linewidths=0.5, alpha=0.5
)

plt.xticks(fontsize=18)
plt.yticks(fontsize=18)

divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.1)

cbar = fig.colorbar(contour_filled, cax=cax)
ax.set_aspect("equal")

Finally, we plot the data. Color bar adjustments were necessary to match the height of the plot.

for f in ["svg", "pdf", "eps", "png"]:
    plt.savefig("velocity.{}".format(f), dpi=300, bbox_inches="tight", pad_inches=0.5)

And finally we save the plot in the desired file formats. A high contour count in vector formats makes the files larger than PNG, but they can be zoomed without losing quality.

Filled contours of velocity magnitude at 200 s

SVG file (5.5M)

Python source for the plotting